18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * vs6624.c ST VS6624 CMOS image sensor driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2011 Analog Devices Inc. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/delay.h> 98c2ecf20Sopenharmony_ci#include <linux/errno.h> 108c2ecf20Sopenharmony_ci#include <linux/gpio.h> 118c2ecf20Sopenharmony_ci#include <linux/i2c.h> 128c2ecf20Sopenharmony_ci#include <linux/init.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/types.h> 168c2ecf20Sopenharmony_ci#include <linux/videodev2.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <media/v4l2-ctrls.h> 198c2ecf20Sopenharmony_ci#include <media/v4l2-device.h> 208c2ecf20Sopenharmony_ci#include <media/v4l2-mediabus.h> 218c2ecf20Sopenharmony_ci#include <media/v4l2-image-sizes.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include "vs6624_regs.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define MAX_FRAME_RATE 30 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistruct vs6624 { 288c2ecf20Sopenharmony_ci struct v4l2_subdev sd; 298c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler hdl; 308c2ecf20Sopenharmony_ci struct v4l2_fract frame_rate; 318c2ecf20Sopenharmony_ci struct v4l2_mbus_framefmt fmt; 328c2ecf20Sopenharmony_ci unsigned ce_pin; 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic const struct vs6624_format { 368c2ecf20Sopenharmony_ci u32 mbus_code; 378c2ecf20Sopenharmony_ci enum v4l2_colorspace colorspace; 388c2ecf20Sopenharmony_ci} vs6624_formats[] = { 398c2ecf20Sopenharmony_ci { 408c2ecf20Sopenharmony_ci .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, 418c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 428c2ecf20Sopenharmony_ci }, 438c2ecf20Sopenharmony_ci { 448c2ecf20Sopenharmony_ci .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, 458c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 468c2ecf20Sopenharmony_ci }, 478c2ecf20Sopenharmony_ci { 488c2ecf20Sopenharmony_ci .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE, 498c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 508c2ecf20Sopenharmony_ci }, 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic const struct v4l2_mbus_framefmt vs6624_default_fmt = { 548c2ecf20Sopenharmony_ci .width = VGA_WIDTH, 558c2ecf20Sopenharmony_ci .height = VGA_HEIGHT, 568c2ecf20Sopenharmony_ci .code = MEDIA_BUS_FMT_UYVY8_2X8, 578c2ecf20Sopenharmony_ci .field = V4L2_FIELD_NONE, 588c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 598c2ecf20Sopenharmony_ci}; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic const u16 vs6624_p1[] = { 628c2ecf20Sopenharmony_ci 0x8104, 0x03, 638c2ecf20Sopenharmony_ci 0x8105, 0x01, 648c2ecf20Sopenharmony_ci 0xc900, 0x03, 658c2ecf20Sopenharmony_ci 0xc904, 0x47, 668c2ecf20Sopenharmony_ci 0xc905, 0x10, 678c2ecf20Sopenharmony_ci 0xc906, 0x80, 688c2ecf20Sopenharmony_ci 0xc907, 0x3a, 698c2ecf20Sopenharmony_ci 0x903a, 0x02, 708c2ecf20Sopenharmony_ci 0x903b, 0x47, 718c2ecf20Sopenharmony_ci 0x903c, 0x15, 728c2ecf20Sopenharmony_ci 0xc908, 0x31, 738c2ecf20Sopenharmony_ci 0xc909, 0xdc, 748c2ecf20Sopenharmony_ci 0xc90a, 0x80, 758c2ecf20Sopenharmony_ci 0xc90b, 0x44, 768c2ecf20Sopenharmony_ci 0x9044, 0x02, 778c2ecf20Sopenharmony_ci 0x9045, 0x31, 788c2ecf20Sopenharmony_ci 0x9046, 0xe2, 798c2ecf20Sopenharmony_ci 0xc90c, 0x07, 808c2ecf20Sopenharmony_ci 0xc90d, 0xe0, 818c2ecf20Sopenharmony_ci 0xc90e, 0x80, 828c2ecf20Sopenharmony_ci 0xc90f, 0x47, 838c2ecf20Sopenharmony_ci 0x9047, 0x90, 848c2ecf20Sopenharmony_ci 0x9048, 0x83, 858c2ecf20Sopenharmony_ci 0x9049, 0x81, 868c2ecf20Sopenharmony_ci 0x904a, 0xe0, 878c2ecf20Sopenharmony_ci 0x904b, 0x60, 888c2ecf20Sopenharmony_ci 0x904c, 0x08, 898c2ecf20Sopenharmony_ci 0x904d, 0x90, 908c2ecf20Sopenharmony_ci 0x904e, 0xc0, 918c2ecf20Sopenharmony_ci 0x904f, 0x43, 928c2ecf20Sopenharmony_ci 0x9050, 0x74, 938c2ecf20Sopenharmony_ci 0x9051, 0x01, 948c2ecf20Sopenharmony_ci 0x9052, 0xf0, 958c2ecf20Sopenharmony_ci 0x9053, 0x80, 968c2ecf20Sopenharmony_ci 0x9054, 0x05, 978c2ecf20Sopenharmony_ci 0x9055, 0xE4, 988c2ecf20Sopenharmony_ci 0x9056, 0x90, 998c2ecf20Sopenharmony_ci 0x9057, 0xc0, 1008c2ecf20Sopenharmony_ci 0x9058, 0x43, 1018c2ecf20Sopenharmony_ci 0x9059, 0xf0, 1028c2ecf20Sopenharmony_ci 0x905a, 0x02, 1038c2ecf20Sopenharmony_ci 0x905b, 0x07, 1048c2ecf20Sopenharmony_ci 0x905c, 0xec, 1058c2ecf20Sopenharmony_ci 0xc910, 0x5d, 1068c2ecf20Sopenharmony_ci 0xc911, 0xca, 1078c2ecf20Sopenharmony_ci 0xc912, 0x80, 1088c2ecf20Sopenharmony_ci 0xc913, 0x5d, 1098c2ecf20Sopenharmony_ci 0x905d, 0xa3, 1108c2ecf20Sopenharmony_ci 0x905e, 0x04, 1118c2ecf20Sopenharmony_ci 0x905f, 0xf0, 1128c2ecf20Sopenharmony_ci 0x9060, 0xa3, 1138c2ecf20Sopenharmony_ci 0x9061, 0x04, 1148c2ecf20Sopenharmony_ci 0x9062, 0xf0, 1158c2ecf20Sopenharmony_ci 0x9063, 0x22, 1168c2ecf20Sopenharmony_ci 0xc914, 0x72, 1178c2ecf20Sopenharmony_ci 0xc915, 0x92, 1188c2ecf20Sopenharmony_ci 0xc916, 0x80, 1198c2ecf20Sopenharmony_ci 0xc917, 0x64, 1208c2ecf20Sopenharmony_ci 0x9064, 0x74, 1218c2ecf20Sopenharmony_ci 0x9065, 0x01, 1228c2ecf20Sopenharmony_ci 0x9066, 0x02, 1238c2ecf20Sopenharmony_ci 0x9067, 0x72, 1248c2ecf20Sopenharmony_ci 0x9068, 0x95, 1258c2ecf20Sopenharmony_ci 0xc918, 0x47, 1268c2ecf20Sopenharmony_ci 0xc919, 0xf2, 1278c2ecf20Sopenharmony_ci 0xc91a, 0x81, 1288c2ecf20Sopenharmony_ci 0xc91b, 0x69, 1298c2ecf20Sopenharmony_ci 0x9169, 0x74, 1308c2ecf20Sopenharmony_ci 0x916a, 0x02, 1318c2ecf20Sopenharmony_ci 0x916b, 0xf0, 1328c2ecf20Sopenharmony_ci 0x916c, 0xec, 1338c2ecf20Sopenharmony_ci 0x916d, 0xb4, 1348c2ecf20Sopenharmony_ci 0x916e, 0x10, 1358c2ecf20Sopenharmony_ci 0x916f, 0x0a, 1368c2ecf20Sopenharmony_ci 0x9170, 0x90, 1378c2ecf20Sopenharmony_ci 0x9171, 0x80, 1388c2ecf20Sopenharmony_ci 0x9172, 0x16, 1398c2ecf20Sopenharmony_ci 0x9173, 0xe0, 1408c2ecf20Sopenharmony_ci 0x9174, 0x70, 1418c2ecf20Sopenharmony_ci 0x9175, 0x04, 1428c2ecf20Sopenharmony_ci 0x9176, 0x90, 1438c2ecf20Sopenharmony_ci 0x9177, 0xd3, 1448c2ecf20Sopenharmony_ci 0x9178, 0xc4, 1458c2ecf20Sopenharmony_ci 0x9179, 0xf0, 1468c2ecf20Sopenharmony_ci 0x917a, 0x22, 1478c2ecf20Sopenharmony_ci 0xc91c, 0x0a, 1488c2ecf20Sopenharmony_ci 0xc91d, 0xbe, 1498c2ecf20Sopenharmony_ci 0xc91e, 0x80, 1508c2ecf20Sopenharmony_ci 0xc91f, 0x73, 1518c2ecf20Sopenharmony_ci 0x9073, 0xfc, 1528c2ecf20Sopenharmony_ci 0x9074, 0xa3, 1538c2ecf20Sopenharmony_ci 0x9075, 0xe0, 1548c2ecf20Sopenharmony_ci 0x9076, 0xf5, 1558c2ecf20Sopenharmony_ci 0x9077, 0x82, 1568c2ecf20Sopenharmony_ci 0x9078, 0x8c, 1578c2ecf20Sopenharmony_ci 0x9079, 0x83, 1588c2ecf20Sopenharmony_ci 0x907a, 0xa3, 1598c2ecf20Sopenharmony_ci 0x907b, 0xa3, 1608c2ecf20Sopenharmony_ci 0x907c, 0xe0, 1618c2ecf20Sopenharmony_ci 0x907d, 0xfc, 1628c2ecf20Sopenharmony_ci 0x907e, 0xa3, 1638c2ecf20Sopenharmony_ci 0x907f, 0xe0, 1648c2ecf20Sopenharmony_ci 0x9080, 0xc3, 1658c2ecf20Sopenharmony_ci 0x9081, 0x9f, 1668c2ecf20Sopenharmony_ci 0x9082, 0xff, 1678c2ecf20Sopenharmony_ci 0x9083, 0xec, 1688c2ecf20Sopenharmony_ci 0x9084, 0x9e, 1698c2ecf20Sopenharmony_ci 0x9085, 0xfe, 1708c2ecf20Sopenharmony_ci 0x9086, 0x02, 1718c2ecf20Sopenharmony_ci 0x9087, 0x0a, 1728c2ecf20Sopenharmony_ci 0x9088, 0xea, 1738c2ecf20Sopenharmony_ci 0xc920, 0x47, 1748c2ecf20Sopenharmony_ci 0xc921, 0x38, 1758c2ecf20Sopenharmony_ci 0xc922, 0x80, 1768c2ecf20Sopenharmony_ci 0xc923, 0x89, 1778c2ecf20Sopenharmony_ci 0x9089, 0xec, 1788c2ecf20Sopenharmony_ci 0x908a, 0xd3, 1798c2ecf20Sopenharmony_ci 0x908b, 0x94, 1808c2ecf20Sopenharmony_ci 0x908c, 0x20, 1818c2ecf20Sopenharmony_ci 0x908d, 0x40, 1828c2ecf20Sopenharmony_ci 0x908e, 0x01, 1838c2ecf20Sopenharmony_ci 0x908f, 0x1c, 1848c2ecf20Sopenharmony_ci 0x9090, 0x90, 1858c2ecf20Sopenharmony_ci 0x9091, 0xd3, 1868c2ecf20Sopenharmony_ci 0x9092, 0xd4, 1878c2ecf20Sopenharmony_ci 0x9093, 0xec, 1888c2ecf20Sopenharmony_ci 0x9094, 0xf0, 1898c2ecf20Sopenharmony_ci 0x9095, 0x02, 1908c2ecf20Sopenharmony_ci 0x9096, 0x47, 1918c2ecf20Sopenharmony_ci 0x9097, 0x3d, 1928c2ecf20Sopenharmony_ci 0xc924, 0x45, 1938c2ecf20Sopenharmony_ci 0xc925, 0xca, 1948c2ecf20Sopenharmony_ci 0xc926, 0x80, 1958c2ecf20Sopenharmony_ci 0xc927, 0x98, 1968c2ecf20Sopenharmony_ci 0x9098, 0x12, 1978c2ecf20Sopenharmony_ci 0x9099, 0x77, 1988c2ecf20Sopenharmony_ci 0x909a, 0xd6, 1998c2ecf20Sopenharmony_ci 0x909b, 0x02, 2008c2ecf20Sopenharmony_ci 0x909c, 0x45, 2018c2ecf20Sopenharmony_ci 0x909d, 0xcd, 2028c2ecf20Sopenharmony_ci 0xc928, 0x20, 2038c2ecf20Sopenharmony_ci 0xc929, 0xd5, 2048c2ecf20Sopenharmony_ci 0xc92a, 0x80, 2058c2ecf20Sopenharmony_ci 0xc92b, 0x9e, 2068c2ecf20Sopenharmony_ci 0x909e, 0x90, 2078c2ecf20Sopenharmony_ci 0x909f, 0x82, 2088c2ecf20Sopenharmony_ci 0x90a0, 0x18, 2098c2ecf20Sopenharmony_ci 0x90a1, 0xe0, 2108c2ecf20Sopenharmony_ci 0x90a2, 0xb4, 2118c2ecf20Sopenharmony_ci 0x90a3, 0x03, 2128c2ecf20Sopenharmony_ci 0x90a4, 0x0e, 2138c2ecf20Sopenharmony_ci 0x90a5, 0x90, 2148c2ecf20Sopenharmony_ci 0x90a6, 0x83, 2158c2ecf20Sopenharmony_ci 0x90a7, 0xbf, 2168c2ecf20Sopenharmony_ci 0x90a8, 0xe0, 2178c2ecf20Sopenharmony_ci 0x90a9, 0x60, 2188c2ecf20Sopenharmony_ci 0x90aa, 0x08, 2198c2ecf20Sopenharmony_ci 0x90ab, 0x90, 2208c2ecf20Sopenharmony_ci 0x90ac, 0x81, 2218c2ecf20Sopenharmony_ci 0x90ad, 0xfc, 2228c2ecf20Sopenharmony_ci 0x90ae, 0xe0, 2238c2ecf20Sopenharmony_ci 0x90af, 0xff, 2248c2ecf20Sopenharmony_ci 0x90b0, 0xc3, 2258c2ecf20Sopenharmony_ci 0x90b1, 0x13, 2268c2ecf20Sopenharmony_ci 0x90b2, 0xf0, 2278c2ecf20Sopenharmony_ci 0x90b3, 0x90, 2288c2ecf20Sopenharmony_ci 0x90b4, 0x81, 2298c2ecf20Sopenharmony_ci 0x90b5, 0xfc, 2308c2ecf20Sopenharmony_ci 0x90b6, 0xe0, 2318c2ecf20Sopenharmony_ci 0x90b7, 0xff, 2328c2ecf20Sopenharmony_ci 0x90b8, 0x02, 2338c2ecf20Sopenharmony_ci 0x90b9, 0x20, 2348c2ecf20Sopenharmony_ci 0x90ba, 0xda, 2358c2ecf20Sopenharmony_ci 0xc92c, 0x70, 2368c2ecf20Sopenharmony_ci 0xc92d, 0xbc, 2378c2ecf20Sopenharmony_ci 0xc92e, 0x80, 2388c2ecf20Sopenharmony_ci 0xc92f, 0xbb, 2398c2ecf20Sopenharmony_ci 0x90bb, 0x90, 2408c2ecf20Sopenharmony_ci 0x90bc, 0x82, 2418c2ecf20Sopenharmony_ci 0x90bd, 0x18, 2428c2ecf20Sopenharmony_ci 0x90be, 0xe0, 2438c2ecf20Sopenharmony_ci 0x90bf, 0xb4, 2448c2ecf20Sopenharmony_ci 0x90c0, 0x03, 2458c2ecf20Sopenharmony_ci 0x90c1, 0x06, 2468c2ecf20Sopenharmony_ci 0x90c2, 0x90, 2478c2ecf20Sopenharmony_ci 0x90c3, 0xc1, 2488c2ecf20Sopenharmony_ci 0x90c4, 0x06, 2498c2ecf20Sopenharmony_ci 0x90c5, 0x74, 2508c2ecf20Sopenharmony_ci 0x90c6, 0x05, 2518c2ecf20Sopenharmony_ci 0x90c7, 0xf0, 2528c2ecf20Sopenharmony_ci 0x90c8, 0x90, 2538c2ecf20Sopenharmony_ci 0x90c9, 0xd3, 2548c2ecf20Sopenharmony_ci 0x90ca, 0xa0, 2558c2ecf20Sopenharmony_ci 0x90cb, 0x02, 2568c2ecf20Sopenharmony_ci 0x90cc, 0x70, 2578c2ecf20Sopenharmony_ci 0x90cd, 0xbf, 2588c2ecf20Sopenharmony_ci 0xc930, 0x72, 2598c2ecf20Sopenharmony_ci 0xc931, 0x21, 2608c2ecf20Sopenharmony_ci 0xc932, 0x81, 2618c2ecf20Sopenharmony_ci 0xc933, 0x3b, 2628c2ecf20Sopenharmony_ci 0x913b, 0x7d, 2638c2ecf20Sopenharmony_ci 0x913c, 0x02, 2648c2ecf20Sopenharmony_ci 0x913d, 0x7f, 2658c2ecf20Sopenharmony_ci 0x913e, 0x7b, 2668c2ecf20Sopenharmony_ci 0x913f, 0x02, 2678c2ecf20Sopenharmony_ci 0x9140, 0x72, 2688c2ecf20Sopenharmony_ci 0x9141, 0x25, 2698c2ecf20Sopenharmony_ci 0xc934, 0x28, 2708c2ecf20Sopenharmony_ci 0xc935, 0xae, 2718c2ecf20Sopenharmony_ci 0xc936, 0x80, 2728c2ecf20Sopenharmony_ci 0xc937, 0xd2, 2738c2ecf20Sopenharmony_ci 0x90d2, 0xf0, 2748c2ecf20Sopenharmony_ci 0x90d3, 0x90, 2758c2ecf20Sopenharmony_ci 0x90d4, 0xd2, 2768c2ecf20Sopenharmony_ci 0x90d5, 0x0a, 2778c2ecf20Sopenharmony_ci 0x90d6, 0x02, 2788c2ecf20Sopenharmony_ci 0x90d7, 0x28, 2798c2ecf20Sopenharmony_ci 0x90d8, 0xb4, 2808c2ecf20Sopenharmony_ci 0xc938, 0x28, 2818c2ecf20Sopenharmony_ci 0xc939, 0xb1, 2828c2ecf20Sopenharmony_ci 0xc93a, 0x80, 2838c2ecf20Sopenharmony_ci 0xc93b, 0xd9, 2848c2ecf20Sopenharmony_ci 0x90d9, 0x90, 2858c2ecf20Sopenharmony_ci 0x90da, 0x83, 2868c2ecf20Sopenharmony_ci 0x90db, 0xba, 2878c2ecf20Sopenharmony_ci 0x90dc, 0xe0, 2888c2ecf20Sopenharmony_ci 0x90dd, 0xff, 2898c2ecf20Sopenharmony_ci 0x90de, 0x90, 2908c2ecf20Sopenharmony_ci 0x90df, 0xd2, 2918c2ecf20Sopenharmony_ci 0x90e0, 0x08, 2928c2ecf20Sopenharmony_ci 0x90e1, 0xe0, 2938c2ecf20Sopenharmony_ci 0x90e2, 0xe4, 2948c2ecf20Sopenharmony_ci 0x90e3, 0xef, 2958c2ecf20Sopenharmony_ci 0x90e4, 0xf0, 2968c2ecf20Sopenharmony_ci 0x90e5, 0xa3, 2978c2ecf20Sopenharmony_ci 0x90e6, 0xe0, 2988c2ecf20Sopenharmony_ci 0x90e7, 0x74, 2998c2ecf20Sopenharmony_ci 0x90e8, 0xff, 3008c2ecf20Sopenharmony_ci 0x90e9, 0xf0, 3018c2ecf20Sopenharmony_ci 0x90ea, 0x90, 3028c2ecf20Sopenharmony_ci 0x90eb, 0xd2, 3038c2ecf20Sopenharmony_ci 0x90ec, 0x0a, 3048c2ecf20Sopenharmony_ci 0x90ed, 0x02, 3058c2ecf20Sopenharmony_ci 0x90ee, 0x28, 3068c2ecf20Sopenharmony_ci 0x90ef, 0xb4, 3078c2ecf20Sopenharmony_ci 0xc93c, 0x29, 3088c2ecf20Sopenharmony_ci 0xc93d, 0x79, 3098c2ecf20Sopenharmony_ci 0xc93e, 0x80, 3108c2ecf20Sopenharmony_ci 0xc93f, 0xf0, 3118c2ecf20Sopenharmony_ci 0x90f0, 0xf0, 3128c2ecf20Sopenharmony_ci 0x90f1, 0x90, 3138c2ecf20Sopenharmony_ci 0x90f2, 0xd2, 3148c2ecf20Sopenharmony_ci 0x90f3, 0x0e, 3158c2ecf20Sopenharmony_ci 0x90f4, 0x02, 3168c2ecf20Sopenharmony_ci 0x90f5, 0x29, 3178c2ecf20Sopenharmony_ci 0x90f6, 0x7f, 3188c2ecf20Sopenharmony_ci 0xc940, 0x29, 3198c2ecf20Sopenharmony_ci 0xc941, 0x7c, 3208c2ecf20Sopenharmony_ci 0xc942, 0x80, 3218c2ecf20Sopenharmony_ci 0xc943, 0xf7, 3228c2ecf20Sopenharmony_ci 0x90f7, 0x90, 3238c2ecf20Sopenharmony_ci 0x90f8, 0x83, 3248c2ecf20Sopenharmony_ci 0x90f9, 0xba, 3258c2ecf20Sopenharmony_ci 0x90fa, 0xe0, 3268c2ecf20Sopenharmony_ci 0x90fb, 0xff, 3278c2ecf20Sopenharmony_ci 0x90fc, 0x90, 3288c2ecf20Sopenharmony_ci 0x90fd, 0xd2, 3298c2ecf20Sopenharmony_ci 0x90fe, 0x0c, 3308c2ecf20Sopenharmony_ci 0x90ff, 0xe0, 3318c2ecf20Sopenharmony_ci 0x9100, 0xe4, 3328c2ecf20Sopenharmony_ci 0x9101, 0xef, 3338c2ecf20Sopenharmony_ci 0x9102, 0xf0, 3348c2ecf20Sopenharmony_ci 0x9103, 0xa3, 3358c2ecf20Sopenharmony_ci 0x9104, 0xe0, 3368c2ecf20Sopenharmony_ci 0x9105, 0x74, 3378c2ecf20Sopenharmony_ci 0x9106, 0xff, 3388c2ecf20Sopenharmony_ci 0x9107, 0xf0, 3398c2ecf20Sopenharmony_ci 0x9108, 0x90, 3408c2ecf20Sopenharmony_ci 0x9109, 0xd2, 3418c2ecf20Sopenharmony_ci 0x910a, 0x0e, 3428c2ecf20Sopenharmony_ci 0x910b, 0x02, 3438c2ecf20Sopenharmony_ci 0x910c, 0x29, 3448c2ecf20Sopenharmony_ci 0x910d, 0x7f, 3458c2ecf20Sopenharmony_ci 0xc944, 0x2a, 3468c2ecf20Sopenharmony_ci 0xc945, 0x42, 3478c2ecf20Sopenharmony_ci 0xc946, 0x81, 3488c2ecf20Sopenharmony_ci 0xc947, 0x0e, 3498c2ecf20Sopenharmony_ci 0x910e, 0xf0, 3508c2ecf20Sopenharmony_ci 0x910f, 0x90, 3518c2ecf20Sopenharmony_ci 0x9110, 0xd2, 3528c2ecf20Sopenharmony_ci 0x9111, 0x12, 3538c2ecf20Sopenharmony_ci 0x9112, 0x02, 3548c2ecf20Sopenharmony_ci 0x9113, 0x2a, 3558c2ecf20Sopenharmony_ci 0x9114, 0x48, 3568c2ecf20Sopenharmony_ci 0xc948, 0x2a, 3578c2ecf20Sopenharmony_ci 0xc949, 0x45, 3588c2ecf20Sopenharmony_ci 0xc94a, 0x81, 3598c2ecf20Sopenharmony_ci 0xc94b, 0x15, 3608c2ecf20Sopenharmony_ci 0x9115, 0x90, 3618c2ecf20Sopenharmony_ci 0x9116, 0x83, 3628c2ecf20Sopenharmony_ci 0x9117, 0xba, 3638c2ecf20Sopenharmony_ci 0x9118, 0xe0, 3648c2ecf20Sopenharmony_ci 0x9119, 0xff, 3658c2ecf20Sopenharmony_ci 0x911a, 0x90, 3668c2ecf20Sopenharmony_ci 0x911b, 0xd2, 3678c2ecf20Sopenharmony_ci 0x911c, 0x10, 3688c2ecf20Sopenharmony_ci 0x911d, 0xe0, 3698c2ecf20Sopenharmony_ci 0x911e, 0xe4, 3708c2ecf20Sopenharmony_ci 0x911f, 0xef, 3718c2ecf20Sopenharmony_ci 0x9120, 0xf0, 3728c2ecf20Sopenharmony_ci 0x9121, 0xa3, 3738c2ecf20Sopenharmony_ci 0x9122, 0xe0, 3748c2ecf20Sopenharmony_ci 0x9123, 0x74, 3758c2ecf20Sopenharmony_ci 0x9124, 0xff, 3768c2ecf20Sopenharmony_ci 0x9125, 0xf0, 3778c2ecf20Sopenharmony_ci 0x9126, 0x90, 3788c2ecf20Sopenharmony_ci 0x9127, 0xd2, 3798c2ecf20Sopenharmony_ci 0x9128, 0x12, 3808c2ecf20Sopenharmony_ci 0x9129, 0x02, 3818c2ecf20Sopenharmony_ci 0x912a, 0x2a, 3828c2ecf20Sopenharmony_ci 0x912b, 0x48, 3838c2ecf20Sopenharmony_ci 0xc900, 0x01, 3848c2ecf20Sopenharmony_ci 0x0000, 0x00, 3858c2ecf20Sopenharmony_ci}; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic const u16 vs6624_p2[] = { 3888c2ecf20Sopenharmony_ci 0x806f, 0x01, 3898c2ecf20Sopenharmony_ci 0x058c, 0x01, 3908c2ecf20Sopenharmony_ci 0x0000, 0x00, 3918c2ecf20Sopenharmony_ci}; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_cistatic const u16 vs6624_run_setup[] = { 3948c2ecf20Sopenharmony_ci 0x1d18, 0x00, /* Enableconstrainedwhitebalance */ 3958c2ecf20Sopenharmony_ci VS6624_PEAK_MIN_OUT_G_MSB, 0x3c, /* Damper PeakGain Output MSB */ 3968c2ecf20Sopenharmony_ci VS6624_PEAK_MIN_OUT_G_LSB, 0x66, /* Damper PeakGain Output LSB */ 3978c2ecf20Sopenharmony_ci VS6624_CM_LOW_THR_MSB, 0x65, /* Damper Low MSB */ 3988c2ecf20Sopenharmony_ci VS6624_CM_LOW_THR_LSB, 0xd1, /* Damper Low LSB */ 3998c2ecf20Sopenharmony_ci VS6624_CM_HIGH_THR_MSB, 0x66, /* Damper High MSB */ 4008c2ecf20Sopenharmony_ci VS6624_CM_HIGH_THR_LSB, 0x62, /* Damper High LSB */ 4018c2ecf20Sopenharmony_ci VS6624_CM_MIN_OUT_MSB, 0x00, /* Damper Min output MSB */ 4028c2ecf20Sopenharmony_ci VS6624_CM_MIN_OUT_LSB, 0x00, /* Damper Min output LSB */ 4038c2ecf20Sopenharmony_ci VS6624_NORA_DISABLE, 0x00, /* Nora fDisable */ 4048c2ecf20Sopenharmony_ci VS6624_NORA_USAGE, 0x04, /* Nora usage */ 4058c2ecf20Sopenharmony_ci VS6624_NORA_LOW_THR_MSB, 0x63, /* Damper Low MSB Changed 0x63 to 0x65 */ 4068c2ecf20Sopenharmony_ci VS6624_NORA_LOW_THR_LSB, 0xd1, /* Damper Low LSB */ 4078c2ecf20Sopenharmony_ci VS6624_NORA_HIGH_THR_MSB, 0x68, /* Damper High MSB */ 4088c2ecf20Sopenharmony_ci VS6624_NORA_HIGH_THR_LSB, 0xdd, /* Damper High LSB */ 4098c2ecf20Sopenharmony_ci VS6624_NORA_MIN_OUT_MSB, 0x3a, /* Damper Min output MSB */ 4108c2ecf20Sopenharmony_ci VS6624_NORA_MIN_OUT_LSB, 0x00, /* Damper Min output LSB */ 4118c2ecf20Sopenharmony_ci VS6624_F2B_DISABLE, 0x00, /* Disable */ 4128c2ecf20Sopenharmony_ci 0x1d8a, 0x30, /* MAXWeightHigh */ 4138c2ecf20Sopenharmony_ci 0x1d91, 0x62, /* fpDamperLowThresholdHigh MSB */ 4148c2ecf20Sopenharmony_ci 0x1d92, 0x4a, /* fpDamperLowThresholdHigh LSB */ 4158c2ecf20Sopenharmony_ci 0x1d95, 0x65, /* fpDamperHighThresholdHigh MSB */ 4168c2ecf20Sopenharmony_ci 0x1d96, 0x0e, /* fpDamperHighThresholdHigh LSB */ 4178c2ecf20Sopenharmony_ci 0x1da1, 0x3a, /* fpMinimumDamperOutputLow MSB */ 4188c2ecf20Sopenharmony_ci 0x1da2, 0xb8, /* fpMinimumDamperOutputLow LSB */ 4198c2ecf20Sopenharmony_ci 0x1e08, 0x06, /* MAXWeightLow */ 4208c2ecf20Sopenharmony_ci 0x1e0a, 0x0a, /* MAXWeightHigh */ 4218c2ecf20Sopenharmony_ci 0x1601, 0x3a, /* Red A MSB */ 4228c2ecf20Sopenharmony_ci 0x1602, 0x14, /* Red A LSB */ 4238c2ecf20Sopenharmony_ci 0x1605, 0x3b, /* Blue A MSB */ 4248c2ecf20Sopenharmony_ci 0x1606, 0x85, /* BLue A LSB */ 4258c2ecf20Sopenharmony_ci 0x1609, 0x3b, /* RED B MSB */ 4268c2ecf20Sopenharmony_ci 0x160a, 0x85, /* RED B LSB */ 4278c2ecf20Sopenharmony_ci 0x160d, 0x3a, /* Blue B MSB */ 4288c2ecf20Sopenharmony_ci 0x160e, 0x14, /* Blue B LSB */ 4298c2ecf20Sopenharmony_ci 0x1611, 0x30, /* Max Distance from Locus MSB */ 4308c2ecf20Sopenharmony_ci 0x1612, 0x8f, /* Max Distance from Locus MSB */ 4318c2ecf20Sopenharmony_ci 0x1614, 0x01, /* Enable constrainer */ 4328c2ecf20Sopenharmony_ci 0x0000, 0x00, 4338c2ecf20Sopenharmony_ci}; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_cistatic const u16 vs6624_default[] = { 4368c2ecf20Sopenharmony_ci VS6624_CONTRAST0, 0x84, 4378c2ecf20Sopenharmony_ci VS6624_SATURATION0, 0x75, 4388c2ecf20Sopenharmony_ci VS6624_GAMMA0, 0x11, 4398c2ecf20Sopenharmony_ci VS6624_CONTRAST1, 0x84, 4408c2ecf20Sopenharmony_ci VS6624_SATURATION1, 0x75, 4418c2ecf20Sopenharmony_ci VS6624_GAMMA1, 0x11, 4428c2ecf20Sopenharmony_ci VS6624_MAN_RG, 0x80, 4438c2ecf20Sopenharmony_ci VS6624_MAN_GG, 0x80, 4448c2ecf20Sopenharmony_ci VS6624_MAN_BG, 0x80, 4458c2ecf20Sopenharmony_ci VS6624_WB_MODE, 0x1, 4468c2ecf20Sopenharmony_ci VS6624_EXPO_COMPENSATION, 0xfe, 4478c2ecf20Sopenharmony_ci VS6624_EXPO_METER, 0x0, 4488c2ecf20Sopenharmony_ci VS6624_LIGHT_FREQ, 0x64, 4498c2ecf20Sopenharmony_ci VS6624_PEAK_GAIN, 0xe, 4508c2ecf20Sopenharmony_ci VS6624_PEAK_LOW_THR, 0x28, 4518c2ecf20Sopenharmony_ci VS6624_HMIRROR0, 0x0, 4528c2ecf20Sopenharmony_ci VS6624_VFLIP0, 0x0, 4538c2ecf20Sopenharmony_ci VS6624_ZOOM_HSTEP0_MSB, 0x0, 4548c2ecf20Sopenharmony_ci VS6624_ZOOM_HSTEP0_LSB, 0x1, 4558c2ecf20Sopenharmony_ci VS6624_ZOOM_VSTEP0_MSB, 0x0, 4568c2ecf20Sopenharmony_ci VS6624_ZOOM_VSTEP0_LSB, 0x1, 4578c2ecf20Sopenharmony_ci VS6624_PAN_HSTEP0_MSB, 0x0, 4588c2ecf20Sopenharmony_ci VS6624_PAN_HSTEP0_LSB, 0xf, 4598c2ecf20Sopenharmony_ci VS6624_PAN_VSTEP0_MSB, 0x0, 4608c2ecf20Sopenharmony_ci VS6624_PAN_VSTEP0_LSB, 0xf, 4618c2ecf20Sopenharmony_ci VS6624_SENSOR_MODE, 0x1, 4628c2ecf20Sopenharmony_ci VS6624_SYNC_CODE_SETUP, 0x21, 4638c2ecf20Sopenharmony_ci VS6624_DISABLE_FR_DAMPER, 0x0, 4648c2ecf20Sopenharmony_ci VS6624_FR_DEN, 0x1, 4658c2ecf20Sopenharmony_ci VS6624_FR_NUM_LSB, 0xf, 4668c2ecf20Sopenharmony_ci VS6624_INIT_PIPE_SETUP, 0x0, 4678c2ecf20Sopenharmony_ci VS6624_IMG_FMT0, 0x0, 4688c2ecf20Sopenharmony_ci VS6624_YUV_SETUP, 0x1, 4698c2ecf20Sopenharmony_ci VS6624_IMAGE_SIZE0, 0x2, 4708c2ecf20Sopenharmony_ci 0x0000, 0x00, 4718c2ecf20Sopenharmony_ci}; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_cistatic inline struct vs6624 *to_vs6624(struct v4l2_subdev *sd) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci return container_of(sd, struct vs6624, sd); 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_cistatic inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) 4788c2ecf20Sopenharmony_ci{ 4798c2ecf20Sopenharmony_ci return &container_of(ctrl->handler, struct vs6624, hdl)->sd; 4808c2ecf20Sopenharmony_ci} 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 4838c2ecf20Sopenharmony_cistatic int vs6624_read(struct v4l2_subdev *sd, u16 index) 4848c2ecf20Sopenharmony_ci{ 4858c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(sd); 4868c2ecf20Sopenharmony_ci u8 buf[2]; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci buf[0] = index >> 8; 4898c2ecf20Sopenharmony_ci buf[1] = index; 4908c2ecf20Sopenharmony_ci i2c_master_send(client, buf, 2); 4918c2ecf20Sopenharmony_ci i2c_master_recv(client, buf, 1); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci return buf[0]; 4948c2ecf20Sopenharmony_ci} 4958c2ecf20Sopenharmony_ci#endif 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cistatic int vs6624_write(struct v4l2_subdev *sd, u16 index, 4988c2ecf20Sopenharmony_ci u8 value) 4998c2ecf20Sopenharmony_ci{ 5008c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(sd); 5018c2ecf20Sopenharmony_ci u8 buf[3]; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci buf[0] = index >> 8; 5048c2ecf20Sopenharmony_ci buf[1] = index; 5058c2ecf20Sopenharmony_ci buf[2] = value; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci return i2c_master_send(client, buf, 3); 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_cistatic int vs6624_writeregs(struct v4l2_subdev *sd, const u16 *regs) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci u16 reg; 5138c2ecf20Sopenharmony_ci u8 data; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci while (*regs != 0x00) { 5168c2ecf20Sopenharmony_ci reg = *regs++; 5178c2ecf20Sopenharmony_ci data = *regs++; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci vs6624_write(sd, reg, data); 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci return 0; 5228c2ecf20Sopenharmony_ci} 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_cistatic int vs6624_s_ctrl(struct v4l2_ctrl *ctrl) 5258c2ecf20Sopenharmony_ci{ 5268c2ecf20Sopenharmony_ci struct v4l2_subdev *sd = to_sd(ctrl); 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci switch (ctrl->id) { 5298c2ecf20Sopenharmony_ci case V4L2_CID_CONTRAST: 5308c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_CONTRAST0, ctrl->val); 5318c2ecf20Sopenharmony_ci break; 5328c2ecf20Sopenharmony_ci case V4L2_CID_SATURATION: 5338c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_SATURATION0, ctrl->val); 5348c2ecf20Sopenharmony_ci break; 5358c2ecf20Sopenharmony_ci case V4L2_CID_HFLIP: 5368c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_HMIRROR0, ctrl->val); 5378c2ecf20Sopenharmony_ci break; 5388c2ecf20Sopenharmony_ci case V4L2_CID_VFLIP: 5398c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_VFLIP0, ctrl->val); 5408c2ecf20Sopenharmony_ci break; 5418c2ecf20Sopenharmony_ci default: 5428c2ecf20Sopenharmony_ci return -EINVAL; 5438c2ecf20Sopenharmony_ci } 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci return 0; 5468c2ecf20Sopenharmony_ci} 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_cistatic int vs6624_enum_mbus_code(struct v4l2_subdev *sd, 5498c2ecf20Sopenharmony_ci struct v4l2_subdev_pad_config *cfg, 5508c2ecf20Sopenharmony_ci struct v4l2_subdev_mbus_code_enum *code) 5518c2ecf20Sopenharmony_ci{ 5528c2ecf20Sopenharmony_ci if (code->pad || code->index >= ARRAY_SIZE(vs6624_formats)) 5538c2ecf20Sopenharmony_ci return -EINVAL; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci code->code = vs6624_formats[code->index].mbus_code; 5568c2ecf20Sopenharmony_ci return 0; 5578c2ecf20Sopenharmony_ci} 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_cistatic int vs6624_set_fmt(struct v4l2_subdev *sd, 5608c2ecf20Sopenharmony_ci struct v4l2_subdev_pad_config *cfg, 5618c2ecf20Sopenharmony_ci struct v4l2_subdev_format *format) 5628c2ecf20Sopenharmony_ci{ 5638c2ecf20Sopenharmony_ci struct v4l2_mbus_framefmt *fmt = &format->format; 5648c2ecf20Sopenharmony_ci struct vs6624 *sensor = to_vs6624(sd); 5658c2ecf20Sopenharmony_ci int index; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci if (format->pad) 5688c2ecf20Sopenharmony_ci return -EINVAL; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++) 5718c2ecf20Sopenharmony_ci if (vs6624_formats[index].mbus_code == fmt->code) 5728c2ecf20Sopenharmony_ci break; 5738c2ecf20Sopenharmony_ci if (index >= ARRAY_SIZE(vs6624_formats)) { 5748c2ecf20Sopenharmony_ci /* default to first format */ 5758c2ecf20Sopenharmony_ci index = 0; 5768c2ecf20Sopenharmony_ci fmt->code = vs6624_formats[0].mbus_code; 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci /* sensor mode is VGA */ 5808c2ecf20Sopenharmony_ci if (fmt->width > VGA_WIDTH) 5818c2ecf20Sopenharmony_ci fmt->width = VGA_WIDTH; 5828c2ecf20Sopenharmony_ci if (fmt->height > VGA_HEIGHT) 5838c2ecf20Sopenharmony_ci fmt->height = VGA_HEIGHT; 5848c2ecf20Sopenharmony_ci fmt->width = fmt->width & (~3); 5858c2ecf20Sopenharmony_ci fmt->height = fmt->height & (~3); 5868c2ecf20Sopenharmony_ci fmt->field = V4L2_FIELD_NONE; 5878c2ecf20Sopenharmony_ci fmt->colorspace = vs6624_formats[index].colorspace; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci if (format->which == V4L2_SUBDEV_FORMAT_TRY) { 5908c2ecf20Sopenharmony_ci cfg->try_fmt = *fmt; 5918c2ecf20Sopenharmony_ci return 0; 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci /* set image format */ 5958c2ecf20Sopenharmony_ci switch (fmt->code) { 5968c2ecf20Sopenharmony_ci case MEDIA_BUS_FMT_UYVY8_2X8: 5978c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_IMG_FMT0, 0x0); 5988c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_YUV_SETUP, 0x1); 5998c2ecf20Sopenharmony_ci break; 6008c2ecf20Sopenharmony_ci case MEDIA_BUS_FMT_YUYV8_2X8: 6018c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_IMG_FMT0, 0x0); 6028c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_YUV_SETUP, 0x3); 6038c2ecf20Sopenharmony_ci break; 6048c2ecf20Sopenharmony_ci case MEDIA_BUS_FMT_RGB565_2X8_LE: 6058c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_IMG_FMT0, 0x4); 6068c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_RGB_SETUP, 0x0); 6078c2ecf20Sopenharmony_ci break; 6088c2ecf20Sopenharmony_ci default: 6098c2ecf20Sopenharmony_ci return -EINVAL; 6108c2ecf20Sopenharmony_ci } 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci /* set image size */ 6138c2ecf20Sopenharmony_ci if ((fmt->width == VGA_WIDTH) && (fmt->height == VGA_HEIGHT)) 6148c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x2); 6158c2ecf20Sopenharmony_ci else if ((fmt->width == QVGA_WIDTH) && (fmt->height == QVGA_HEIGHT)) 6168c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x4); 6178c2ecf20Sopenharmony_ci else if ((fmt->width == QQVGA_WIDTH) && (fmt->height == QQVGA_HEIGHT)) 6188c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x6); 6198c2ecf20Sopenharmony_ci else if ((fmt->width == CIF_WIDTH) && (fmt->height == CIF_HEIGHT)) 6208c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x3); 6218c2ecf20Sopenharmony_ci else if ((fmt->width == QCIF_WIDTH) && (fmt->height == QCIF_HEIGHT)) 6228c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x5); 6238c2ecf20Sopenharmony_ci else if ((fmt->width == QQCIF_WIDTH) && (fmt->height == QQCIF_HEIGHT)) 6248c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x7); 6258c2ecf20Sopenharmony_ci else { 6268c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x8); 6278c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_MAN_HSIZE0_MSB, fmt->width >> 8); 6288c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_MAN_HSIZE0_LSB, fmt->width & 0xFF); 6298c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_MAN_VSIZE0_MSB, fmt->height >> 8); 6308c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_MAN_VSIZE0_LSB, fmt->height & 0xFF); 6318c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_CROP_CTRL0, 0x1); 6328c2ecf20Sopenharmony_ci } 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci sensor->fmt = *fmt; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci return 0; 6378c2ecf20Sopenharmony_ci} 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_cistatic int vs6624_get_fmt(struct v4l2_subdev *sd, 6408c2ecf20Sopenharmony_ci struct v4l2_subdev_pad_config *cfg, 6418c2ecf20Sopenharmony_ci struct v4l2_subdev_format *format) 6428c2ecf20Sopenharmony_ci{ 6438c2ecf20Sopenharmony_ci struct vs6624 *sensor = to_vs6624(sd); 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci if (format->pad) 6468c2ecf20Sopenharmony_ci return -EINVAL; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci format->format = sensor->fmt; 6498c2ecf20Sopenharmony_ci return 0; 6508c2ecf20Sopenharmony_ci} 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_cistatic int vs6624_g_frame_interval(struct v4l2_subdev *sd, 6538c2ecf20Sopenharmony_ci struct v4l2_subdev_frame_interval *ival) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci struct vs6624 *sensor = to_vs6624(sd); 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci ival->interval.numerator = sensor->frame_rate.denominator; 6588c2ecf20Sopenharmony_ci ival->interval.denominator = sensor->frame_rate.numerator; 6598c2ecf20Sopenharmony_ci return 0; 6608c2ecf20Sopenharmony_ci} 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_cistatic int vs6624_s_frame_interval(struct v4l2_subdev *sd, 6638c2ecf20Sopenharmony_ci struct v4l2_subdev_frame_interval *ival) 6648c2ecf20Sopenharmony_ci{ 6658c2ecf20Sopenharmony_ci struct vs6624 *sensor = to_vs6624(sd); 6668c2ecf20Sopenharmony_ci struct v4l2_fract *tpf = &ival->interval; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci if (tpf->numerator == 0 || tpf->denominator == 0 6708c2ecf20Sopenharmony_ci || (tpf->denominator > tpf->numerator * MAX_FRAME_RATE)) { 6718c2ecf20Sopenharmony_ci /* reset to max frame rate */ 6728c2ecf20Sopenharmony_ci tpf->numerator = 1; 6738c2ecf20Sopenharmony_ci tpf->denominator = MAX_FRAME_RATE; 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci sensor->frame_rate.numerator = tpf->denominator; 6768c2ecf20Sopenharmony_ci sensor->frame_rate.denominator = tpf->numerator; 6778c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0); 6788c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_FR_NUM_MSB, 6798c2ecf20Sopenharmony_ci sensor->frame_rate.numerator >> 8); 6808c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_FR_NUM_LSB, 6818c2ecf20Sopenharmony_ci sensor->frame_rate.numerator & 0xFF); 6828c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_FR_DEN, 6838c2ecf20Sopenharmony_ci sensor->frame_rate.denominator & 0xFF); 6848c2ecf20Sopenharmony_ci return 0; 6858c2ecf20Sopenharmony_ci} 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_cistatic int vs6624_s_stream(struct v4l2_subdev *sd, int enable) 6888c2ecf20Sopenharmony_ci{ 6898c2ecf20Sopenharmony_ci if (enable) 6908c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_USER_CMD, 0x2); 6918c2ecf20Sopenharmony_ci else 6928c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_USER_CMD, 0x4); 6938c2ecf20Sopenharmony_ci udelay(100); 6948c2ecf20Sopenharmony_ci return 0; 6958c2ecf20Sopenharmony_ci} 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 6988c2ecf20Sopenharmony_cistatic int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 6998c2ecf20Sopenharmony_ci{ 7008c2ecf20Sopenharmony_ci reg->val = vs6624_read(sd, reg->reg & 0xffff); 7018c2ecf20Sopenharmony_ci reg->size = 1; 7028c2ecf20Sopenharmony_ci return 0; 7038c2ecf20Sopenharmony_ci} 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_cistatic int vs6624_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) 7068c2ecf20Sopenharmony_ci{ 7078c2ecf20Sopenharmony_ci vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff); 7088c2ecf20Sopenharmony_ci return 0; 7098c2ecf20Sopenharmony_ci} 7108c2ecf20Sopenharmony_ci#endif 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vs6624_ctrl_ops = { 7138c2ecf20Sopenharmony_ci .s_ctrl = vs6624_s_ctrl, 7148c2ecf20Sopenharmony_ci}; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_core_ops vs6624_core_ops = { 7178c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 7188c2ecf20Sopenharmony_ci .g_register = vs6624_g_register, 7198c2ecf20Sopenharmony_ci .s_register = vs6624_s_register, 7208c2ecf20Sopenharmony_ci#endif 7218c2ecf20Sopenharmony_ci}; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_video_ops vs6624_video_ops = { 7248c2ecf20Sopenharmony_ci .s_frame_interval = vs6624_s_frame_interval, 7258c2ecf20Sopenharmony_ci .g_frame_interval = vs6624_g_frame_interval, 7268c2ecf20Sopenharmony_ci .s_stream = vs6624_s_stream, 7278c2ecf20Sopenharmony_ci}; 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_pad_ops vs6624_pad_ops = { 7308c2ecf20Sopenharmony_ci .enum_mbus_code = vs6624_enum_mbus_code, 7318c2ecf20Sopenharmony_ci .get_fmt = vs6624_get_fmt, 7328c2ecf20Sopenharmony_ci .set_fmt = vs6624_set_fmt, 7338c2ecf20Sopenharmony_ci}; 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_ops vs6624_ops = { 7368c2ecf20Sopenharmony_ci .core = &vs6624_core_ops, 7378c2ecf20Sopenharmony_ci .video = &vs6624_video_ops, 7388c2ecf20Sopenharmony_ci .pad = &vs6624_pad_ops, 7398c2ecf20Sopenharmony_ci}; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_cistatic int vs6624_probe(struct i2c_client *client, 7428c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 7438c2ecf20Sopenharmony_ci{ 7448c2ecf20Sopenharmony_ci struct vs6624 *sensor; 7458c2ecf20Sopenharmony_ci struct v4l2_subdev *sd; 7468c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl; 7478c2ecf20Sopenharmony_ci const unsigned *ce; 7488c2ecf20Sopenharmony_ci int ret; 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci /* Check if the adapter supports the needed features */ 7518c2ecf20Sopenharmony_ci if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 7528c2ecf20Sopenharmony_ci return -EIO; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci ce = client->dev.platform_data; 7558c2ecf20Sopenharmony_ci if (ce == NULL) 7568c2ecf20Sopenharmony_ci return -EINVAL; 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci ret = devm_gpio_request_one(&client->dev, *ce, GPIOF_OUT_INIT_HIGH, 7598c2ecf20Sopenharmony_ci "VS6624 Chip Enable"); 7608c2ecf20Sopenharmony_ci if (ret) { 7618c2ecf20Sopenharmony_ci v4l_err(client, "failed to request GPIO %d\n", *ce); 7628c2ecf20Sopenharmony_ci return ret; 7638c2ecf20Sopenharmony_ci } 7648c2ecf20Sopenharmony_ci /* wait 100ms before any further i2c writes are performed */ 7658c2ecf20Sopenharmony_ci msleep(100); 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); 7688c2ecf20Sopenharmony_ci if (sensor == NULL) 7698c2ecf20Sopenharmony_ci return -ENOMEM; 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci sd = &sensor->sd; 7728c2ecf20Sopenharmony_ci v4l2_i2c_subdev_init(sd, client, &vs6624_ops); 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci vs6624_writeregs(sd, vs6624_p1); 7758c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_MICRO_EN, 0x2); 7768c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_DIO_EN, 0x1); 7778c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 7788c2ecf20Sopenharmony_ci vs6624_writeregs(sd, vs6624_p2); 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci vs6624_writeregs(sd, vs6624_default); 7818c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_HSYNC_SETUP, 0xF); 7828c2ecf20Sopenharmony_ci vs6624_writeregs(sd, vs6624_run_setup); 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci /* set frame rate */ 7858c2ecf20Sopenharmony_ci sensor->frame_rate.numerator = MAX_FRAME_RATE; 7868c2ecf20Sopenharmony_ci sensor->frame_rate.denominator = 1; 7878c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0); 7888c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_FR_NUM_MSB, 7898c2ecf20Sopenharmony_ci sensor->frame_rate.numerator >> 8); 7908c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_FR_NUM_LSB, 7918c2ecf20Sopenharmony_ci sensor->frame_rate.numerator & 0xFF); 7928c2ecf20Sopenharmony_ci vs6624_write(sd, VS6624_FR_DEN, 7938c2ecf20Sopenharmony_ci sensor->frame_rate.denominator & 0xFF); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci sensor->fmt = vs6624_default_fmt; 7968c2ecf20Sopenharmony_ci sensor->ce_pin = *ce; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci v4l_info(client, "chip found @ 0x%02x (%s)\n", 7998c2ecf20Sopenharmony_ci client->addr << 1, client->adapter->name); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci hdl = &sensor->hdl; 8028c2ecf20Sopenharmony_ci v4l2_ctrl_handler_init(hdl, 4); 8038c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, 8048c2ecf20Sopenharmony_ci V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x87); 8058c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, 8068c2ecf20Sopenharmony_ci V4L2_CID_SATURATION, 0, 0xFF, 1, 0x78); 8078c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, 8088c2ecf20Sopenharmony_ci V4L2_CID_HFLIP, 0, 1, 1, 0); 8098c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, 8108c2ecf20Sopenharmony_ci V4L2_CID_VFLIP, 0, 1, 1, 0); 8118c2ecf20Sopenharmony_ci /* hook the control handler into the driver */ 8128c2ecf20Sopenharmony_ci sd->ctrl_handler = hdl; 8138c2ecf20Sopenharmony_ci if (hdl->error) { 8148c2ecf20Sopenharmony_ci int err = hdl->error; 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(hdl); 8178c2ecf20Sopenharmony_ci return err; 8188c2ecf20Sopenharmony_ci } 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci /* initialize the hardware to the default control values */ 8218c2ecf20Sopenharmony_ci ret = v4l2_ctrl_handler_setup(hdl); 8228c2ecf20Sopenharmony_ci if (ret) 8238c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(hdl); 8248c2ecf20Sopenharmony_ci return ret; 8258c2ecf20Sopenharmony_ci} 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_cistatic int vs6624_remove(struct i2c_client *client) 8288c2ecf20Sopenharmony_ci{ 8298c2ecf20Sopenharmony_ci struct v4l2_subdev *sd = i2c_get_clientdata(client); 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci v4l2_device_unregister_subdev(sd); 8328c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(sd->ctrl_handler); 8338c2ecf20Sopenharmony_ci return 0; 8348c2ecf20Sopenharmony_ci} 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_cistatic const struct i2c_device_id vs6624_id[] = { 8378c2ecf20Sopenharmony_ci {"vs6624", 0}, 8388c2ecf20Sopenharmony_ci {}, 8398c2ecf20Sopenharmony_ci}; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, vs6624_id); 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_cistatic struct i2c_driver vs6624_driver = { 8448c2ecf20Sopenharmony_ci .driver = { 8458c2ecf20Sopenharmony_ci .name = "vs6624", 8468c2ecf20Sopenharmony_ci }, 8478c2ecf20Sopenharmony_ci .probe = vs6624_probe, 8488c2ecf20Sopenharmony_ci .remove = vs6624_remove, 8498c2ecf20Sopenharmony_ci .id_table = vs6624_id, 8508c2ecf20Sopenharmony_ci}; 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_cimodule_i2c_driver(vs6624_driver); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("VS6624 sensor driver"); 8558c2ecf20Sopenharmony_ciMODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); 8568c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 857