diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index f6a606e1..f1fe8f72 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -3,9 +3,12 @@ subdir-ccflags-y += -Werror +obj-m += max9295.o +obj-m += max9296.o obj-m += nv_imx185.o obj-m += nv_imx274.o obj-m += nv_imx318.o +obj-m += nv_imx390.o obj-m += nv_ov5693.o obj-m += max96712.o obj-m += nv_ar0234.o diff --git a/drivers/media/i2c/imx390_mode_tbls.h b/drivers/media/i2c/imx390_mode_tbls.h new file mode 100644 index 00000000..1c8885e3 --- /dev/null +++ b/drivers/media/i2c/imx390_mode_tbls.h @@ -0,0 +1,3269 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ +/* + * imx390_mode_tbls.h - imx390 sensor mode tables + */ + +#ifndef __IMX390_I2C_TABLES__ +#define __IMX390_I2C_TABLES__ + +#include + +#define IMX390_TABLE_WAIT_MS 0xff00 +#define IMX390_TABLE_END 0xff01 +#define IMX390_MAX_RETRIES 3 +#define IMX390_WAIT_MS_STOP 1 +#define IMX390_WAIT_MS_START 30 +#define IMX390_WAIT_MS_STREAM 210 +#define IMX390_GAIN_TABLE_SIZE 255 + +#define imx390_reg struct reg_8 + +static imx390_reg imx390_start[] = { + {0x0000, 0x00}, + + { IMX390_TABLE_END, 0x00} +}; + +static imx390_reg imx390_stop[] = { + {0x0000, 0x01}, + + {IMX390_TABLE_END, 0x00} +}; + +static imx390_reg imx390_1920x1080_crop_30fps[] = { + {0x000C, 0x7F}, + {0x000D, 0x01}, + {0x000E, 0x00}, + {0x0010, 0x7F}, + {0x0011, 0x01}, + {0x0012, 0x00}, + {0x0018, 0x50}, + {0x0019, 0x00}, + {0x001A, 0x0C}, + {0x001B, 0x00}, + {0x0038, 0x00}, + {0x003C, 0x00}, + {0x003D, 0x00}, + {0x003E, 0x00}, + {0x0040, 0x00}, + {0x0041, 0x00}, + {0x0042, 0x00}, + {0x0044, 0x00}, + {0x0045, 0x00}, + {0x0046, 0x00}, + {0x0048, 0x00}, + {0x0049, 0x00}, + {0x004A, 0x00}, + {0x004C, 0x00}, + {0x004D, 0x00}, + {0x004E, 0x00}, + {0x0050, 0x00}, + {0x0051, 0x00}, + {0x0052, 0x00}, + {0x0054, 0x00}, + {0x0055, 0x00}, + {0x0056, 0x00}, + {0x0058, 0x00}, + {0x0059, 0x00}, + {0x005A, 0x00}, + {0x005C, 0x00}, + {0x005D, 0x00}, + {0x005E, 0x00}, + {0x0060, 0x00}, + {0x0061, 0x00}, + {0x0062, 0x00}, + {0x0064, 0x00}, + {0x0065, 0x00}, + {0x0066, 0x00}, + {0x0068, 0x00}, + {0x0069, 0x00}, + {0x006A, 0x00}, + {0x0078, 0x01}, + {0x007C, 0x08}, + {0x007D, 0x00}, + {0x0080, 0x08}, + {0x0081, 0x00}, + {0x00F4, 0x1C}, + {0x00F5, 0xF8}, + {0x00F6, 0x01}, + {0x00F8, 0x03}, + {0x00F9, 0x00}, + {0x00FA, 0x01}, + {0x00FB, 0x02}, + {0x0114, 0x00}, + {0x0115, 0x01}, + {0x0118, 0x20}, + {0x0119, 0x03}, + {0x011A, 0x00}, + {0x011B, 0x41}, + {0x011C, 0x80}, + {0x011D, 0x00}, + {0x0120, 0x20}, + {0x0121, 0x00}, + {0x0122, 0x00}, + {0x0123, 0x44}, + {0x0124, 0x00}, + {0x0125, 0x01}, + {0x0128, 0xAC}, + {0x0129, 0x0D}, + {0x012A, 0x00}, + {0x012B, 0xA4}, + {0x012C, 0x00}, + {0x012D, 0x01}, + {0x0130, 0xC4}, + {0x0131, 0x09}, + {0x0132, 0x00}, + {0x0133, 0xDA}, + {0x013A, 0x00}, + {0x013B, 0x01}, + {0x013C, 0x00}, + {0x013D, 0x00}, + {0x013E, 0x00}, + {0x0140, 0x00}, + {0x0141, 0x00}, + {0x0142, 0x00}, + {0x0144, 0x80}, + {0x0145, 0x01}, + {0x0146, 0x00}, + {0x0148, 0x80}, + {0x0149, 0x01}, + {0x014A, 0x00}, + {0x014C, 0xD6}, + {0x014D, 0x06}, + {0x014E, 0x00}, + {0x0150, 0x47}, + {0x0151, 0x03}, + {0x0152, 0x00}, + {0x0154, 0xAC}, + {0x0155, 0x0D}, + {0x0156, 0x00}, + {0x0158, 0x09}, + {0x0159, 0x04}, + {0x015A, 0x00}, + {0x015C, 0xC0}, + {0x015D, 0x5D}, + {0x015E, 0x00}, + {0x0160, 0xCA}, + {0x0161, 0x05}, + {0x0162, 0x00}, + {0x0164, 0x80}, + {0x0165, 0xBB}, + {0x0166, 0x00}, + {0x0168, 0xD1}, + {0x0169, 0x06}, + {0x016A, 0x00}, + {0x016C, 0x3A}, + {0x016D, 0xB5}, + {0x016E, 0x01}, + {0x0170, 0x2E}, + {0x0171, 0x08}, + {0x0172, 0x00}, + {0x0174, 0x60}, + {0x0175, 0xE3}, + {0x0176, 0x16}, + {0x0178, 0x12}, + {0x0179, 0x0B}, + {0x017A, 0x00}, + {0x017C, 0x90}, + {0x017D, 0x51}, + {0x017E, 0x2D}, + {0x0180, 0x9A}, + {0x0181, 0x0C}, + {0x0182, 0x00}, + {0x0184, 0xEE}, + {0x0185, 0x3E}, + {0x0186, 0x75}, + {0x0188, 0x0E}, + {0x0189, 0x0F}, + {0x018A, 0x00}, + {0x018C, 0xFF}, + {0x018D, 0xFF}, + {0x018E, 0xFF}, + {0x0190, 0x0E}, + {0x0191, 0x0F}, + {0x0192, 0x00}, + {0x0194, 0x0E}, + {0x0195, 0x0F}, + {0x0196, 0x00}, + {0x0198, 0x00}, + {0x0199, 0x00}, + {0x019A, 0x00}, + {0x019B, 0x01}, + {0x019C, 0x55}, + {0x019D, 0x55}, + {0x019E, 0x55}, + {0x019F, 0x00}, + {0x01A0, 0xC7}, + {0x01A1, 0x71}, + {0x01A2, 0x1C}, + {0x01A3, 0x00}, + {0x01A4, 0x7C}, + {0x01A5, 0x9A}, + {0x01A6, 0x05}, + {0x01A7, 0x00}, + {0x01A8, 0x3E}, + {0x01A9, 0xCD}, + {0x01AA, 0x02}, + {0x01AB, 0x00}, + {0x01AC, 0x9F}, + {0x01AD, 0x66}, + {0x01AE, 0x01}, + {0x01AF, 0x00}, + {0x01B0, 0xED}, + {0x01B1, 0x22}, + {0x01B2, 0x00}, + {0x01B3, 0x00}, + {0x01B4, 0x76}, + {0x01B5, 0x11}, + {0x01B6, 0x00}, + {0x01B7, 0x00}, + {0x01B8, 0xBB}, + {0x01B9, 0x08}, + {0x01BA, 0x00}, + {0x01BB, 0x00}, + {0x01BC, 0x00}, + {0x01BD, 0x00}, + {0x01BE, 0x00}, + {0x01BF, 0x00}, + {0x01C0, 0x00}, + {0x01C1, 0x00}, + {0x01C2, 0x00}, + {0x01C3, 0x00}, + {0x01C4, 0x00}, + {0x01C5, 0x00}, + {0x01CC, 0x01}, + {0x01D0, 0x09}, + {0x01D4, 0x01}, + {0x0232, 0x45}, + {0x0233, 0x00}, + {0x0390, 0x00}, + {0x0391, 0x00}, + {0x0392, 0x00}, + {0x03C0, 0x01}, + {0x2000, 0x55}, + {0x2001, 0x55}, + {0x2002, 0x55}, + {0x2003, 0x05}, + {0x2004, 0x02}, + {0x2008, 0x65}, + {0x2009, 0x04}, + {0x200A, 0x00}, + {0x200C, 0x30}, + {0x200D, 0x11}, + {0x2010, 0x04}, + {0x2014, 0x01}, + {0x2018, 0x02}, + {0x2019, 0x04}, + {0x201A, 0x00}, + {0x201C, 0x21}, + {0x201D, 0x11}, + {0x201E, 0x00}, + {0x201F, 0x00}, + {0x2020, 0xBC}, + {0x2021, 0x00}, + {0x2022, 0x7F}, + {0x2023, 0x00}, + {0x2024, 0xBA}, + {0x2025, 0x00}, + {0x2026, 0x81}, + {0x2027, 0x00}, + {0x2028, 0x7D}, + {0x2029, 0x90}, + {0x202A, 0x05}, + {0x202C, 0xFC}, + {0x202D, 0x02}, + {0x202E, 0x25}, + {0x202F, 0x03}, + {0x2030, 0x05}, + {0x2031, 0x02}, + {0x2032, 0xCA}, + {0x2033, 0x02}, + {0x2034, 0xFC}, + {0x2035, 0x02}, + {0x2036, 0x25}, + {0x2037, 0x03}, + {0x2038, 0x25}, + {0x2039, 0x97}, + {0x203A, 0xEC}, + {0x203B, 0x01}, + {0x203C, 0xF5}, + {0x203D, 0x8E}, + {0x203E, 0x0C}, + {0x203F, 0x2D}, + {0x2040, 0x69}, + {0x2041, 0x01}, + {0x2042, 0x8E}, + {0x2043, 0x01}, + {0x2044, 0x0C}, + {0x2045, 0x02}, + {0x2046, 0x31}, + {0x2047, 0x02}, + {0x2048, 0x6A}, + {0x2049, 0x01}, + {0x204A, 0x8E}, + {0x204B, 0x01}, + {0x204C, 0x0D}, + {0x204D, 0x02}, + {0x204E, 0x31}, + {0x204F, 0x02}, + {0x2050, 0x7B}, + {0x2051, 0x00}, + {0x2052, 0x7D}, + {0x2053, 0x00}, + {0x2054, 0x95}, + {0x2055, 0x00}, + {0x2056, 0x97}, + {0x2057, 0x00}, + {0x2058, 0xAD}, + {0x2059, 0x00}, + {0x205A, 0xAF}, + {0x205B, 0x00}, + {0x205C, 0x92}, + {0x205D, 0x00}, + {0x205E, 0x94}, + {0x205F, 0x00}, + {0x2060, 0x8E}, + {0x2061, 0x00}, + {0x2062, 0x90}, + {0x2063, 0x00}, + {0x2064, 0xB1}, + {0x2065, 0x00}, + {0x2066, 0xB3}, + {0x2067, 0x00}, + {0x2068, 0x08}, + {0x2069, 0x00}, + {0x206A, 0x04}, + {0x206B, 0x00}, + {0x206C, 0x84}, + {0x206D, 0x00}, + {0x206E, 0x80}, + {0x206F, 0x00}, + {0x2070, 0x04}, + {0x2071, 0x00}, + {0x2072, 0x46}, + {0x2073, 0x00}, + {0x2074, 0xE9}, + {0x2075, 0x01}, + {0x2076, 0x74}, + {0x2077, 0x02}, + {0x2078, 0x80}, + {0x2079, 0x00}, + {0x207A, 0xC1}, + {0x207B, 0x00}, + {0x207C, 0xFF}, + {0x207D, 0x03}, + {0x207E, 0xFF}, + {0x207F, 0x03}, + {0x2080, 0x78}, + {0x2081, 0x00}, + {0x2082, 0x6A}, + {0x2083, 0x01}, + {0x2084, 0xE4}, + {0x2085, 0x01}, + {0x2086, 0x2B}, + {0x2087, 0x03}, + {0x2088, 0x00}, + {0x2089, 0x00}, + {0x208A, 0xFF}, + {0x208B, 0x03}, + {0x208C, 0xFF}, + {0x208D, 0x03}, + {0x208E, 0xFF}, + {0x208F, 0x03}, + {0x2090, 0x7D}, + {0x2091, 0x00}, + {0x2092, 0x62}, + {0x2093, 0x01}, + {0x2094, 0xE9}, + {0x2095, 0x01}, + {0x2096, 0x00}, + {0x2097, 0x00}, + {0x2098, 0x7C}, + {0x2099, 0x00}, + {0x209A, 0x21}, + {0x209B, 0x03}, + {0x209C, 0xE9}, + {0x209D, 0x01}, + {0x209E, 0x21}, + {0x209F, 0x03}, + {0x20A0, 0xFF}, + {0x20A1, 0x03}, + {0x20A2, 0xFF}, + {0x20A3, 0x03}, + {0x20A4, 0xFF}, + {0x20A5, 0x03}, + {0x20A6, 0xFF}, + {0x20A7, 0x03}, + {0x20A8, 0xFF}, + {0x20A9, 0x03}, + {0x20AA, 0xFF}, + {0x20AB, 0x03}, + {0x20AC, 0xFF}, + {0x20AD, 0x03}, + {0x20AE, 0xFF}, + {0x20AF, 0x03}, + {0x20B0, 0xFF}, + {0x20B1, 0x03}, + {0x20B2, 0xFF}, + {0x20B3, 0x03}, + {0x20B4, 0x87}, + {0x20B5, 0xCC}, + {0x20B6, 0x87}, + {0x20B7, 0x08}, + {0x20B8, 0xF4}, + {0x20B9, 0xA5}, + {0x20BA, 0x07}, + {0x20BC, 0x1F}, + {0x20BD, 0x01}, + {0x20BE, 0xF6}, + {0x20BF, 0x00}, + {0x20C0, 0x90}, + {0x20C1, 0x01}, + {0x20C2, 0x67}, + {0x20C3, 0x01}, + {0x20C4, 0xFF}, + {0x20C5, 0x03}, + {0x20C6, 0xFF}, + {0x20C7, 0x03}, + {0x20C8, 0x33}, + {0x20C9, 0x02}, + {0x20CA, 0x0A}, + {0x20CB, 0x02}, + {0x20CC, 0x7F}, + {0x20CD, 0x00}, + {0x20CE, 0xD2}, + {0x20CF, 0x00}, + {0x20D0, 0x81}, + {0x20D1, 0x00}, + {0x20D2, 0x87}, + {0x20D3, 0x00}, + {0x20D4, 0x09}, + {0x20D5, 0x00}, + {0x20D8, 0x7F}, + {0x20D9, 0x00}, + {0x20DA, 0x62}, + {0x20DB, 0x01}, + {0x20DC, 0x7F}, + {0x20DD, 0x00}, + {0x20DE, 0x62}, + {0x20DF, 0x01}, + {0x20E0, 0x65}, + {0x20E1, 0x00}, + {0x20E2, 0x75}, + {0x20E3, 0x00}, + {0x20E4, 0xE0}, + {0x20E5, 0x00}, + {0x20E6, 0xF0}, + {0x20E7, 0x00}, + {0x20E8, 0x4C}, + {0x20E9, 0x01}, + {0x20EA, 0x5C}, + {0x20EB, 0x01}, + {0x20EC, 0xD1}, + {0x20ED, 0x01}, + {0x20EE, 0xE1}, + {0x20EF, 0x01}, + {0x20F0, 0x93}, + {0x20F1, 0x02}, + {0x20F2, 0xA3}, + {0x20F3, 0x02}, + {0x20F4, 0x0D}, + {0x20F5, 0x03}, + {0x20F6, 0x1D}, + {0x20F7, 0x03}, + {0x20F8, 0x57}, + {0x20F9, 0x00}, + {0x20FA, 0x7B}, + {0x20FB, 0x00}, + {0x20FC, 0xD2}, + {0x20FD, 0x00}, + {0x20FE, 0xF6}, + {0x20FF, 0x00}, + {0x2100, 0x3E}, + {0x2101, 0x01}, + {0x2102, 0x60}, + {0x2103, 0x01}, + {0x2104, 0xC3}, + {0x2105, 0x01}, + {0x2106, 0xE5}, + {0x2107, 0x01}, + {0x2108, 0x85}, + {0x2109, 0x02}, + {0x210A, 0xA9}, + {0x210B, 0x02}, + {0x210C, 0xFF}, + {0x210D, 0x02}, + {0x210E, 0x21}, + {0x210F, 0x03}, + {0x2110, 0xFF}, + {0x2111, 0x03}, + {0x2112, 0x00}, + {0x2113, 0x00}, + {0x2114, 0xFF}, + {0x2115, 0x03}, + {0x2116, 0xFF}, + {0x2117, 0x03}, + {0x2118, 0xFF}, + {0x2119, 0x03}, + {0x211A, 0xFF}, + {0x211B, 0x03}, + {0x211C, 0xFF}, + {0x211D, 0x03}, + {0x211E, 0xFF}, + {0x211F, 0x03}, + {0x2120, 0xFF}, + {0x2121, 0x03}, + {0x2122, 0xFF}, + {0x2123, 0x03}, + {0x2124, 0xFF}, + {0x2125, 0x03}, + {0x2126, 0xFF}, + {0x2127, 0x03}, + {0x2128, 0x7D}, + {0x2129, 0x90}, + {0x212A, 0xD5}, + {0x212B, 0x07}, + {0x212C, 0x64}, + {0x212D, 0x01}, + {0x2130, 0x5F}, + {0x2131, 0x7D}, + {0x2132, 0x05}, + {0x2134, 0x78}, + {0x2135, 0x00}, + {0x2136, 0x76}, + {0x2137, 0x00}, + {0x2138, 0xF3}, + {0x2139, 0x00}, + {0x213A, 0xF1}, + {0x213B, 0x00}, + {0x213C, 0xA6}, + {0x213D, 0x02}, + {0x213E, 0xA4}, + {0x213F, 0x02}, + {0x2140, 0x7D}, + {0x2141, 0x00}, + {0x2142, 0x8D}, + {0x2143, 0x00}, + {0x2144, 0xA1}, + {0x2145, 0x01}, + {0x2146, 0xB1}, + {0x2147, 0x01}, + {0x2148, 0xAB}, + {0x2149, 0x02}, + {0x214A, 0xBB}, + {0x214B, 0x02}, + {0x214C, 0x17}, + {0x214D, 0x5C}, + {0x214E, 0x00}, + {0x2150, 0x00}, + {0x2151, 0x00}, + {0x2152, 0xF8}, + {0x2153, 0x00}, + {0x2154, 0xBE}, + {0x2155, 0x00}, + {0x2156, 0x7D}, + {0x2157, 0x00}, + {0x2158, 0x25}, + {0x2159, 0x00}, + {0x215A, 0x7D}, + {0x215B, 0x00}, + {0x215C, 0x62}, + {0x215D, 0x01}, + {0x215E, 0xFF}, + {0x215F, 0x03}, + {0x2160, 0x26}, + {0x2161, 0x00}, + {0x2162, 0x7D}, + {0x2163, 0x00}, + {0x2164, 0x63}, + {0x2165, 0x01}, + {0x2166, 0xFF}, + {0x2167, 0x03}, + {0x2168, 0xCB}, + {0x2169, 0x02}, + {0x216A, 0xCF}, + {0x216B, 0x02}, + {0x216C, 0xFF}, + {0x216D, 0x03}, + {0x216E, 0xFF}, + {0x216F, 0x03}, + {0x2170, 0xFF}, + {0x2171, 0x03}, + {0x2172, 0xFF}, + {0x2173, 0x03}, + {0x2174, 0xFF}, + {0x2175, 0x03}, + {0x2176, 0xFF}, + {0x2177, 0x03}, + {0x2178, 0x7E}, + {0x2179, 0x00}, + {0x217A, 0xBD}, + {0x217B, 0x00}, + {0x217C, 0xEC}, + {0x217D, 0x01}, + {0x217E, 0x7B}, + {0x217F, 0x02}, + {0x2180, 0xD1}, + {0x2181, 0x02}, + {0x2182, 0x25}, + {0x2183, 0x03}, + {0x2184, 0x7F}, + {0x2185, 0x00}, + {0x2186, 0xBD}, + {0x2187, 0x00}, + {0x2188, 0xED}, + {0x2189, 0x01}, + {0x218A, 0x7B}, + {0x218B, 0x02}, + {0x218C, 0xD2}, + {0x218D, 0x02}, + {0x218E, 0x25}, + {0x218F, 0x03}, + {0x2190, 0xFF}, + {0x2191, 0x03}, + {0x2192, 0xFF}, + {0x2193, 0x03}, + {0x2194, 0xE9}, + {0x2195, 0x01}, + {0x2196, 0x21}, + {0x2197, 0x03}, + {0x2198, 0x17}, + {0x2199, 0xFC}, + {0x219A, 0x7F}, + {0x219B, 0x01}, + {0x219C, 0xFF}, + {0x219D, 0x03}, + {0x21A0, 0x1B}, + {0x21A1, 0x1B}, + {0x21A2, 0x1B}, + {0x21A3, 0x1B}, + {0x21A4, 0x2A}, + {0x21A5, 0x80}, + {0x21A6, 0x00}, + {0x21A8, 0x04}, + {0x21A9, 0x98}, + {0x21AA, 0x60}, + {0x21AB, 0x03}, + {0x21AC, 0x7F}, + {0x21AD, 0x80}, + {0x21AE, 0x09}, + {0x21B0, 0x1C}, + {0x21B1, 0x00}, + {0x21B2, 0xA0}, + {0x21B3, 0x00}, + {0x21B4, 0x0C}, + {0x21B5, 0x00}, + {0x21B6, 0x2D}, + {0x21B7, 0x00}, + {0x21B8, 0x20}, + {0x21B9, 0x00}, + {0x21BA, 0x02}, + {0x21BB, 0x00}, + {0x21BC, 0xCC}, + {0x21BD, 0x00}, + {0x21BE, 0x4A}, + {0x21BF, 0x00}, + {0x21C0, 0xD0}, + {0x21C1, 0x00}, + {0x21C2, 0x44}, + {0x21C3, 0x00}, + {0x21C4, 0x00}, + {0x21C5, 0xE0}, + {0x21C6, 0x00}, + {0x21C8, 0x11}, + {0x21C9, 0x00}, + {0x21CA, 0x02}, + {0x21CC, 0x08}, + {0x21CD, 0xC0}, + {0x21CE, 0x0C}, + {0x21D0, 0x44}, + {0x21D1, 0x00}, + {0x21D2, 0x02}, + {0x21D4, 0x02}, + {0x21D5, 0x20}, + {0x21D6, 0x2C}, + {0x21D8, 0xFE}, + {0x21D9, 0x9D}, + {0x21DA, 0xDF}, + {0x21DB, 0x03}, + {0x21DC, 0x62}, + {0x21DD, 0x01}, + {0x21DE, 0x7F}, + {0x21DF, 0x00}, + {0x21E0, 0xB7}, + {0x21E1, 0x01}, + {0x21E2, 0xB5}, + {0x21E3, 0x01}, + {0x21E4, 0xC1}, + {0x21E5, 0x02}, + {0x21E6, 0xBF}, + {0x21E7, 0x02}, + {0x21E8, 0xB3}, + {0x21E9, 0x0D}, + {0x21EA, 0x00}, + {0x21EB, 0x04}, + {0x21EC, 0x90}, + {0x21ED, 0x07}, + {0x21EE, 0x58}, + {0x21EF, 0x04}, + {0x21F0, 0x54}, + {0x21F1, 0x04}, + {0x21F4, 0x02}, + {0x21F5, 0x00}, + {0x21F6, 0x00}, + {0x21F8, 0x3C}, + {0x21F9, 0x00}, + {0x21FC, 0x28}, + {0x21FD, 0x00}, + {0x21FE, 0x3C}, + {0x21FF, 0x00}, + {0x2200, 0x00}, + {0x2204, 0x4C}, + {0x2205, 0x04}, + {0x2206, 0x65}, + {0x2207, 0x04}, + {0x2208, 0x0A}, + {0x2209, 0x00}, + {0x220C, 0x57}, + {0x220D, 0x00}, + {0x220E, 0x37}, + {0x220F, 0x00}, + {0x2210, 0x1F}, + {0x2211, 0x00}, + {0x2212, 0x1F}, + {0x2213, 0x00}, + {0x2214, 0x1F}, + {0x2215, 0x00}, + {0x2216, 0x77}, + {0x2217, 0x00}, + {0x2218, 0x1F}, + {0x2219, 0x00}, + {0x221A, 0x17}, + {0x221B, 0x00}, + {0x221C, 0x03}, + {0x2220, 0x24}, + {0x2221, 0x00}, + {0x2222, 0x00}, + {0x2223, 0x00}, + {0x2224, 0xA7}, + {0x2225, 0xAA}, + {0x2226, 0x80}, + {0x2227, 0x08}, + {0x2228, 0x01}, + {0x22B2, 0x92}, + {0x22B4, 0x20}, + {0x22B5, 0x00}, + {0x22B6, 0x20}, + {0x22B7, 0x00}, + {0x22B8, 0x20}, + {0x22B9, 0x00}, + {0x22BA, 0x20}, + {0x22BB, 0x00}, + {0x22BC, 0x20}, + {0x22BD, 0x00}, + {0x22BE, 0x20}, + {0x22BF, 0x00}, + {0x22C0, 0x20}, + {0x22C1, 0x00}, + {0x22C2, 0x20}, + {0x22C3, 0x00}, + {0x22C4, 0x20}, + {0x22C5, 0x00}, + {0x22C6, 0x20}, + {0x22C7, 0x00}, + {0x22C8, 0x20}, + {0x22C9, 0x00}, + {0x22CA, 0x20}, + {0x22CB, 0x00}, + {0x22CC, 0x20}, + {0x22CD, 0x00}, + {0x22CE, 0x20}, + {0x22CF, 0x00}, + {0x22DA, 0x00}, + {0x2308, 0x01}, + {0x2311, 0x09}, + {0x2318, 0x40}, + {0x2319, 0xCD}, + {0x231A, 0x54}, + {0x2324, 0x10}, + {0x2325, 0x00}, + {0x2328, 0x00}, + {0x2354, 0x0C}, + {0x23C0, 0x5D}, + {0x244C, 0x00}, + {0x244D, 0x02}, + {0x244E, 0x54}, + {0x244F, 0x02}, + {0x24A0, 0x00}, + {0x24DA, 0x6F}, + {0x24DB, 0x00}, + {0x24DC, 0x62}, + {0x24DD, 0x01}, + {0x24EA, 0x32}, + {0x24EB, 0x00}, + {0x24EC, 0xDC}, + {0x24ED, 0x00}, + {0x24FA, 0x32}, + {0x24FB, 0x00}, + {0x24FC, 0xDD}, + {0x24FD, 0x00}, + {0x254A, 0x15}, + {0x254B, 0x01}, + {0x255A, 0x15}, + {0x255B, 0x01}, + {0x2560, 0x01}, + {0x2561, 0x00}, + {0x2562, 0x2A}, + {0x2563, 0x00}, + {0x2564, 0xF8}, + {0x2565, 0x00}, + {0x2566, 0x15}, + {0x2567, 0x01}, + {0x2568, 0x0C}, + {0x2569, 0x02}, + {0x256A, 0x31}, + {0x256B, 0x02}, + {0x2578, 0x90}, + {0x2579, 0x01}, + {0x257A, 0x92}, + {0x257B, 0x01}, + {0x257C, 0xB8}, + {0x257D, 0x02}, + {0x257E, 0xBA}, + {0x257F, 0x02}, + {0x2584, 0x90}, + {0x2585, 0x01}, + {0x2586, 0x92}, + {0x2587, 0x01}, + {0x2588, 0xB8}, + {0x2589, 0x02}, + {0x258A, 0xBA}, + {0x258B, 0x02}, + {0x26B8, 0x10}, + {0x26B9, 0x00}, + {0x26BA, 0x33}, + {0x26BB, 0x00}, + {0x26BC, 0x89}, + {0x26BD, 0x00}, + {0x26BE, 0xB0}, + {0x26BF, 0x00}, + {0x26C4, 0x4E}, + {0x26C5, 0x00}, + {0x26C8, 0xC9}, + {0x26C9, 0x00}, + {0x26CC, 0x35}, + {0x26CD, 0x01}, + {0x26D0, 0xBA}, + {0x26D1, 0x01}, + {0x26D4, 0x7C}, + {0x26D5, 0x02}, + {0x26D8, 0xF6}, + {0x26D9, 0x02}, + {0x26DE, 0x51}, + {0x26DF, 0x00}, + {0x26E0, 0x7F}, + {0x26E1, 0x00}, + {0x26E2, 0xCC}, + {0x26E3, 0x00}, + {0x26E4, 0xF8}, + {0x26E5, 0x00}, + {0x26E6, 0x38}, + {0x26E7, 0x01}, + {0x26E8, 0x65}, + {0x26E9, 0x01}, + {0x26EA, 0xBD}, + {0x26EB, 0x01}, + {0x26EE, 0x7F}, + {0x26EF, 0x02}, + {0x26F0, 0xAB}, + {0x26F1, 0x02}, + {0x26F2, 0xF9}, + {0x26F3, 0x02}, + {0x2722, 0x63}, + {0x2723, 0x02}, + {0x2938, 0x55}, + {0x2939, 0x00}, + {0x293A, 0x17}, + {0x293B, 0x00}, + {0x293C, 0xD0}, + {0x293D, 0x00}, + {0x293E, 0x91}, + {0x293F, 0x00}, + {0x2940, 0x3C}, + {0x2941, 0x01}, + {0x2942, 0x0C}, + {0x2943, 0x01}, + {0x2944, 0xC1}, + {0x2945, 0x01}, + {0x2946, 0x76}, + {0x2947, 0x01}, + {0x2948, 0x83}, + {0x2949, 0x02}, + {0x294A, 0xFB}, + {0x294B, 0x01}, + {0x294C, 0xFD}, + {0x294D, 0x02}, + {0x294E, 0xBF}, + {0x294F, 0x02}, + {0x2A06, 0xFF}, + {0x2A07, 0x03}, + {0x2A20, 0x00}, + {0x2A21, 0x00}, + {0x2A22, 0x7D}, + {0x2A23, 0x00}, + {0x2B11, 0x19}, + {0x2B13, 0x11}, + {0x2B14, 0x11}, + {0x2B15, 0x11}, + {0x2B16, 0x11}, + {0x2B17, 0x10}, + {0x2B18, 0x0F}, + {0x2B19, 0x0E}, + {0x2B1A, 0x0D}, + {0x2B1B, 0x0C}, + {0x2B1C, 0x0B}, + {0x2B1D, 0x0B}, + {0x2B1E, 0x0A}, + {0x2B1F, 0x09}, + {0x2B20, 0x08}, + {0x2B21, 0x07}, + {0x2B22, 0x06}, + {0x2B23, 0x05}, + {0x2B24, 0x04}, + {0x2B25, 0x03}, + {0x2B26, 0x03}, + {0x2B38, 0x01}, + {0x2B45, 0xE3}, + {0x2B50, 0x01}, + {0x2B51, 0x00}, + {0x2B6D, 0x47}, + {0x2B70, 0x02}, + {0x2B71, 0x02}, + {0x2B72, 0x02}, + {0x2B7F, 0x7F}, + {0x2B80, 0x94}, + {0x2B81, 0x06}, + {0x2B87, 0x1B}, + {0x2B88, 0x1B}, + {0x2B89, 0x17}, + {0x2B8A, 0x12}, + {0x2B8B, 0x12}, + {0x2B8D, 0x2B}, + {0x2B8E, 0x2B}, + {0x2B8F, 0x2B}, + {0x2B90, 0x7F}, + {0x2B91, 0x1F}, + {0x2B94, 0xFE}, + {0x2B95, 0x26}, + {0x2B98, 0xFE}, + {0x2B99, 0x56}, + {0x2BA8, 0xBC}, + {0x2BA9, 0x62}, + {0x2BC1, 0x70}, + {0x2BC5, 0x80}, + {0x2BD5, 0x30}, + {0x2BD6, 0xF0}, + {0x2BD8, 0xDB}, + {0x2BD9, 0xF6}, + {0x2BDA, 0x63}, + {0x2BDB, 0x0C}, + {0x2BDC, 0x5C}, + {0x2C98, 0xE1}, + {0x2C99, 0x2E}, + {0x2C9B, 0x86}, + {0x2CA9, 0x80}, + {0x2CAA, 0x01}, + {0x2D39, 0x0E}, + {0x2D54, 0x00}, + + {0x2E18, 0x0}, + + {0x2D5B, 0x58}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x23}, + {0x3003, 0xA1}, + {0x3004, 0x00}, + {0x3005, 0x20}, + {0x3006, 0x58}, + {0x3007, 0x00}, + {0x3008, 0x06}, + {0x3009, 0xB4}, + {0x300A, 0x1F}, + {0x300B, 0x00}, + {0x300C, 0x00}, + {0x300D, 0x1B}, + {0x300E, 0x90}, + {0x300F, 0x97}, + {0x3010, 0x00}, + {0x3011, 0x00}, + {0x3012, 0x20}, + {0x3013, 0x21}, + {0x3014, 0x00}, + {0x3015, 0x20}, + {0x3016, 0x84}, + {0x3017, 0x00}, + {0x3018, 0x30}, + {0x3019, 0x09}, + {0x301A, 0x46}, + {0x301B, 0x00}, + {0x3070, 0xC1}, + {0x3071, 0x81}, + {0x3072, 0x29}, + {0x3073, 0x81}, + {0x3370, 0x01}, + {0x3374, 0xF0}, + {0x3375, 0x00}, + {0x3376, 0x01}, + {0x3377, 0x00}, + {0x3410, 0x80},/* crop_h_size */ + {0x3411, 0x07}, + {0x3418, 0x34},/* crop_v_size */ + {0x3419, 0x04}, + {0x3450, 0x00},/* use continuous clock */ + {0x34A0, 0x00}, + {0x34C0, 0xD3}, + {0x34C1, 0x00}, + {0x34C2, 0xD3}, + {0x34C3, 0x00}, + {0x34C4, 0xD3}, + {0x34C5, 0x00}, + {0x34C6, 0xD3}, + {0x34C7, 0x00}, + {0x34C8, 0xE2}, + {0x34C9, 0x21}, + {0x34CA, 0xE0}, + {0x34CB, 0x1F}, + {0x34CC, 0x06}, + {0x34CD, 0x20}, + {0x34CE, 0x28}, + {0x34CF, 0x1F}, + {0x3584, 0x00}, + {0x3586, 0x00}, + {0x3587, 0x01}, + {0x3588, 0xE6}, + {0x3589, 0x00}, + {0x3590, 0x00}, + {0x3591, 0x00}, + {0x3594, 0x40}, + {0x3598, 0x03}, + {0x3599, 0x00}, + {0x359A, 0x80}, + {0x359B, 0x00}, + {0x359C, 0x00}, + {0x359D, 0x01}, + {0x359E, 0x00}, + {0x359F, 0x02}, + {0x35A0, 0x00}, + {0x35A1, 0x04}, + {0x35A2, 0x20}, + {0x35A3, 0x00}, + {0x35A4, 0x40}, + {0x35A5, 0x00}, + {0x35A6, 0x80}, + {0x35A7, 0x00}, + {0x35A8, 0x00}, + {0x35A9, 0x01}, + {0x35AA, 0x3A}, + {0x35AB, 0x00}, + {0x35AC, 0x80}, + {0x35AD, 0x00}, + {0x35AE, 0x00}, + {0x35AF, 0x01}, + {0x35B0, 0x00}, + {0x35B1, 0x02}, + {0x35B2, 0x00}, + {0x35B3, 0x04}, + {0x35B4, 0x02}, + {0x35B5, 0x00}, + {0x35B6, 0x04}, + {0x35B7, 0x00}, + {0x35B8, 0x08}, + {0x35B9, 0x00}, + {0x35BA, 0x10}, + {0x35BB, 0x00}, + {0x35BC, 0x03}, + {0x35BD, 0x00}, + {0x35C8, 0x00}, + {0x35C9, 0x01}, + {0x35CA, 0x00}, + {0x35CB, 0x04}, + {0x35CC, 0x00}, + {0x35CD, 0x10}, + {0x35CE, 0x00}, + {0x35CF, 0x40}, + {0x35D0, 0x00}, + {0x35D1, 0x0C}, + {0x35D2, 0x00}, + {0x35D3, 0x0C}, + {0x35D4, 0x00}, + {0x35D5, 0x0C}, + {0x35D6, 0x00}, + {0x35D7, 0x0C}, + {0x35D8, 0x00}, + {0x35D9, 0x00}, + {0x35DA, 0x08}, + {0x35DB, 0x00}, + {0x35DC, 0xD8}, + {0x35DD, 0x0E}, + {0x35F0, 0x00}, + {0x35F1, 0x10}, + {0x35F2, 0x00}, + {0x35F3, 0x10}, + {0x35F4, 0x00}, + {0x35F5, 0x10}, + {0x35F6, 0x00}, + {0x35F7, 0x03}, + {0x35F8, 0x00}, + {0x35F9, 0x01}, + {0x35FA, 0x38}, + {0x35FB, 0x00}, + {0x35FC, 0xB3}, + {0x35FD, 0x01}, + {0x35FE, 0x00}, + {0x35FF, 0x00}, + {0x3600, 0x05}, + {0x3601, 0x06}, + {0x3604, 0x03}, + {0x3605, 0x00}, + {0x3608, 0x03}, + {0x3609, 0x00}, + {0x360C, 0x00}, + {0x360D, 0x00}, + {0x3610, 0x10}, + {0x3611, 0x01}, + {0x3612, 0x00}, + {0x3613, 0x00}, + {0x3614, 0x00}, + {0x3615, 0x00}, + {0x361C, 0x00}, + {0x361D, 0x01}, + {0x361E, 0x00}, + {0x361F, 0x01}, + {0x3620, 0x01}, + {0x3621, 0x00}, + {0x3622, 0xB0}, + {0x3623, 0x04}, + {0x3624, 0xDC}, + {0x3625, 0x05}, + {0x3626, 0x00}, + {0x3627, 0x01}, + {0x3628, 0xFF}, + {0x3629, 0x0F}, + {0x362A, 0x00}, + {0x362B, 0x10}, + {0x362C, 0x00}, + {0x362D, 0x01}, + {0x3630, 0x40}, + {0x3631, 0x00}, + {0x3632, 0x40}, + {0x3633, 0x00}, + {0x3634, 0x40}, + {0x3635, 0x00}, + {0x3636, 0x40}, + {0x3637, 0x00}, + {0x3638, 0x40}, + {0x3639, 0x00}, + {0x363A, 0x40}, + {0x363B, 0x00}, + {0x363C, 0x40}, + {0x363D, 0x00}, + {0x363E, 0x40}, + {0x363F, 0x00}, + {0x36C4, 0x99}, + {0x36C5, 0x09}, + {0x36C6, 0x18}, + {0x36C7, 0x07}, + {0x36C8, 0x65}, + {0x36C9, 0x0E}, + {0x36CC, 0x99}, + {0x36CD, 0x01}, + {0x36CE, 0x47}, + {0x36CF, 0x00}, + {0x36D0, 0x04}, + {0x36D1, 0x00}, + {0x36D4, 0x65}, + {0x36D5, 0x0E}, + {0x36D6, 0xA4}, + {0x36D7, 0x0A}, + {0x36D8, 0x65}, + {0x36D9, 0x0E}, + {0x36DC, 0x65}, + {0x36DD, 0x0E}, + {0x36DE, 0xA4}, + {0x36DF, 0x0A}, + {0x36E0, 0x65}, + {0x36E1, 0x0E}, + {0x36E4, 0x65}, + {0x36E5, 0x0E}, + {0x36E6, 0xA4}, + {0x36E7, 0x0A}, + {0x36E8, 0x65}, + {0x36E9, 0x0E}, + {0x36EE, 0x00}, + {0x36EF, 0x00}, + {0x36F0, 0x00}, + {0x36F1, 0x80}, + {0x36F8, 0x00}, + {0x3702, 0x03}, + {0x3703, 0x04}, + {0x3704, 0x08}, + {0x370E, 0x0E}, + {0x3718, 0x64}, + {0x3719, 0x47}, + {0x371A, 0x36}, + {0x371B, 0x1E}, + {0x371C, 0x64}, + {0x371D, 0x41}, + {0x371E, 0x2F}, + {0x371F, 0x1A}, + {0x3720, 0x9C}, + {0x3721, 0xA4}, + {0x3722, 0xAC}, + {0x3723, 0xB4}, + {0x3748, 0xAA}, + {0x3749, 0x96}, + {0x374A, 0x7D}, + {0x374B, 0x69}, + {0x37C0, 0x00}, + {0x37C1, 0x00}, + {0x37C2, 0x00}, + {0x37C4, 0x00}, + {0x37C5, 0x00}, + {0x37C6, 0x00}, + {0x37C8, 0x00}, + {0x37C9, 0x00}, + {0x37CA, 0x00}, + {0x37CC, 0x00}, + {0x37CD, 0x00}, + {0x37CE, 0x00}, + {0x37D0, 0x00}, + {0x37D1, 0x00}, + {0x37D2, 0x00}, + {0x37D4, 0x00}, + {0x37D5, 0x00}, + {0x37D6, 0x00}, + {0x37D8, 0x00}, + {0x37D9, 0x00}, + {0x37DA, 0x00}, + {0x37DC, 0x00}, + {0x37DD, 0x00}, + {0x37DE, 0x00}, + {0x37E0, 0x00}, + {0x37E1, 0x00}, + {0x37E2, 0x00}, + {0x37E4, 0x00}, + {0x37E5, 0x00}, + {0x37E6, 0x00}, + {0x37E8, 0x00}, + {0x37E9, 0x00}, + {0x37EA, 0x00}, + {0x37EC, 0x00}, + {0x37ED, 0x00}, + {0x37EE, 0x00}, + {0x37F0, 0x00}, + {0x37F4, 0x00}, + {0x37F5, 0x1E}, + {0x37F6, 0x34}, + {0x37F7, 0x00}, + {0x37F8, 0xFF}, + {0x37F9, 0xFF}, + {0x37FA, 0x03}, + {0x37FC, 0x00}, + {0x37FD, 0x00}, + {0x37FE, 0x04}, + {0x3800, 0xFF}, + {0x3801, 0xFF}, + {0x3802, 0x03}, + {0x3804, 0x00}, + {0x3805, 0x00}, + {0x3806, 0x04}, + {0x3808, 0x00}, + {0x3809, 0x00}, + {0x380A, 0x00}, + {0x380C, 0x00}, + {0x380D, 0x00}, + {0x380E, 0x00}, + {0x3810, 0x00}, + {0x3811, 0x00}, + {0x3812, 0x00}, + {0x3814, 0x00}, + {0x3815, 0x00}, + {0x3816, 0x00}, + {0x3818, 0x00}, + {0x3819, 0x00}, + {0x381A, 0x00}, + {0x381C, 0x00}, + {0x381D, 0x00}, + {0x381E, 0x00}, + {0x3820, 0x00}, + {0x3821, 0x00}, + {0x3822, 0x00}, + {0x3824, 0x00}, + {0x3825, 0x00}, + {0x3826, 0x00}, + {0x3828, 0x00}, + {0x3829, 0x00}, + {0x382A, 0x00}, + {0x382C, 0x00}, + {0x382D, 0x00}, + {0x382E, 0x00}, + {0x3830, 0x00}, + {0x3831, 0x00}, + {0x3832, 0x00}, + {0x3834, 0x00}, + {0x3835, 0x00}, + {0x3836, 0x00}, + {0x3838, 0x00}, + {0x3839, 0x00}, + {0x383A, 0x00}, + {0x383B, 0x00}, + {0x383C, 0x00}, + {0x383D, 0x00}, + {0x383E, 0x00}, + {0x383F, 0x00}, + {0x3840, 0x00}, + {0x3841, 0x00}, + {0x3842, 0x00}, + {0x3843, 0x00}, + {0x3844, 0x00}, + {0x3845, 0x00}, + {0x3846, 0x00}, + {0x3847, 0x00}, + {0x3848, 0x00}, + {0x3849, 0x00}, + {0x384A, 0x00}, + {0x384B, 0x00}, + {0x384C, 0x00}, + {0x384D, 0x00}, + {0x384E, 0x00}, + {0x384F, 0x00}, + {0x3850, 0xFF}, + {0x3851, 0x0F}, + {0x3852, 0x00}, + {0x3853, 0x10}, + {0x3854, 0xFF}, + {0x3855, 0x0F}, + {0x3856, 0x00}, + {0x3857, 0x10}, + {0x3858, 0xFF}, + {0x3859, 0x0F}, + {0x385A, 0x00}, + {0x385B, 0x10}, + {0x385C, 0x02}, + {0x385D, 0x00}, + {0x385E, 0x06}, + {0x385F, 0x00}, + {0x3860, 0x06}, + {0x3861, 0x00}, + {0x3862, 0x08}, + {0x3863, 0x00}, + {0x3864, 0x02}, + {0x3865, 0x00}, + {0x38A0, 0x01}, + {0x38A1, 0x01}, + {0x38A2, 0x00}, + {0x38A3, 0x01}, + {0x38A4, 0x07}, + {0x38A5, 0x00}, + {0x38A6, 0x04}, + {0x38A7, 0x05}, + {0x38A8, 0x00}, + {0x38A9, 0x00}, + {0x38AC, 0x00}, + {0x38AD, 0x00}, + {0x38AE, 0x01}, + {0x38B0, 0x02}, + {0x38B2, 0x43}, + {0x38B3, 0x00}, + {0x38B4, 0x10}, + {0x38B5, 0x00}, + {0x38B6, 0x09}, + {0x38B7, 0x00}, + {0x38B8, 0x09}, + {0x38B9, 0x00}, + {0x38BA, 0x47}, + {0x38BB, 0x00}, + {0x38BC, 0x16}, + {0x38BD, 0x00}, + {0x38BE, 0x0E}, + {0x38BF, 0x00}, + {0x38C0, 0x0B}, + {0x38C1, 0x00}, + {0x38C2, 0x4A}, + {0x38C3, 0x00}, + {0x38C4, 0x1C}, + {0x38C5, 0x00}, + {0x38C6, 0x12}, + {0x38C7, 0x00}, + {0x38C8, 0x0D}, + {0x38C9, 0x00}, + {0x38CA, 0x51}, + {0x38CB, 0x00}, + {0x38CC, 0x24}, + {0x38CD, 0x00}, + {0x38CE, 0x19}, + {0x38CF, 0x00}, + {0x38D0, 0x10}, + {0x38D1, 0x00}, + {0x38D2, 0x5D}, + {0x38D3, 0x00}, + {0x38D4, 0x30}, + {0x38D5, 0x00}, + {0x38D6, 0x23}, + {0x38D7, 0x00}, + {0x38D8, 0x17}, + {0x38D9, 0x00}, + {0x38DA, 0x72}, + {0x38DB, 0x00}, + {0x38DC, 0x43}, + {0x38DD, 0x00}, + {0x38DE, 0x31}, + {0x38DF, 0x00}, + {0x38E0, 0x20}, + {0x38E1, 0x00}, + {0x38E2, 0x96}, + {0x38E3, 0x00}, + {0x38E4, 0x5E}, + {0x38E5, 0x00}, + {0x38E6, 0x46}, + {0x38E7, 0x00}, + {0x38E8, 0x2E}, + {0x38E9, 0x00}, + {0x38EA, 0xD4}, + {0x38EB, 0x00}, + {0x38EC, 0x87}, + {0x38ED, 0x00}, + {0x38EE, 0x65}, + {0x38EF, 0x00}, + {0x38F0, 0x43}, + {0x38F1, 0x00}, + {0x38F2, 0x3F}, + {0x38F3, 0x01}, + {0x38F4, 0xC4}, + {0x38F5, 0x00}, + {0x38F6, 0x94}, + {0x38F7, 0x00}, + {0x38F8, 0x64}, + {0x38F9, 0x00}, + {0x38FA, 0x00}, + {0x38FB, 0x01}, + {0x38FC, 0x00}, + {0x38FD, 0x01}, + {0x38FE, 0x00}, + {0x38FF, 0x01}, + {0x3900, 0x00}, + {0x3901, 0x01}, + {0x3902, 0x70}, + {0x3903, 0x00}, + {0x3904, 0x30}, + {0x3905, 0x00}, + {0x3906, 0x25}, + {0x3907, 0x00}, + {0x3908, 0x20}, + {0x3909, 0x00}, + {0x390A, 0xB2}, + {0x390B, 0x00}, + {0x390C, 0x80}, + {0x390D, 0x00}, + {0x390E, 0x70}, + {0x390F, 0x00}, + {0x3910, 0x50}, + {0x3911, 0x00}, + {0x3912, 0xB2}, + {0x3913, 0x00}, + {0x3914, 0x80}, + {0x3915, 0x00}, + {0x3916, 0x70}, + {0x3917, 0x00}, + {0x3918, 0x50}, + {0x3919, 0x00}, + {0x391A, 0xB2}, + {0x391B, 0x00}, + {0x391C, 0x80}, + {0x391D, 0x00}, + {0x391E, 0x70}, + {0x391F, 0x00}, + {0x3920, 0x50}, + {0x3921, 0x00}, + {0x3922, 0x40}, + {0x3923, 0x00}, + {0x3924, 0x40}, + {0x3925, 0x00}, + {0x3926, 0x40}, + {0x3927, 0x00}, + {0x3928, 0x40}, + {0x3929, 0x00}, + {0x392A, 0x80}, + {0x392B, 0x00}, + {0x392C, 0x80}, + {0x392D, 0x00}, + {0x392E, 0x80}, + {0x392F, 0x00}, + {0x3930, 0x80}, + {0x3931, 0x00}, + {0x3932, 0x80}, + {0x3933, 0x80}, + {0x3934, 0x80}, + {0x3940, 0x01}, + {0x3941, 0x01}, + {0x3942, 0x00}, + {0x3943, 0x01}, + {0x3944, 0x07}, + {0x3945, 0x00}, + {0x3946, 0x04}, + {0x3947, 0x05}, + {0x3948, 0x00}, + {0x3949, 0x00}, + {0x394C, 0x00}, + {0x394D, 0x00}, + {0x394E, 0x01}, + {0x3950, 0x03}, + {0x3952, 0x27}, + {0x3953, 0x00}, + {0x3954, 0x0C}, + {0x3955, 0x00}, + {0x3956, 0x09}, + {0x3957, 0x00}, + {0x3958, 0x07}, + {0x3959, 0x00}, + {0x395A, 0x29}, + {0x395B, 0x00}, + {0x395C, 0x0E}, + {0x395D, 0x00}, + {0x395E, 0x0B}, + {0x395F, 0x00}, + {0x3960, 0x08}, + {0x3961, 0x00}, + {0x3962, 0x2B}, + {0x3963, 0x00}, + {0x3964, 0x10}, + {0x3965, 0x00}, + {0x3966, 0x0C}, + {0x3967, 0x00}, + {0x3968, 0x09}, + {0x3969, 0x00}, + {0x396A, 0x2E}, + {0x396B, 0x00}, + {0x396C, 0x13}, + {0x396D, 0x00}, + {0x396E, 0x0E}, + {0x396F, 0x00}, + {0x3970, 0x0A}, + {0x3971, 0x00}, + {0x3972, 0x35}, + {0x3973, 0x00}, + {0x3974, 0x19}, + {0x3975, 0x00}, + {0x3976, 0x12}, + {0x3977, 0x00}, + {0x3978, 0x0D}, + {0x3979, 0x00}, + {0x397A, 0x41}, + {0x397B, 0x00}, + {0x397C, 0x21}, + {0x397D, 0x00}, + {0x397E, 0x19}, + {0x397F, 0x00}, + {0x3980, 0x11}, + {0x3981, 0x00}, + {0x3982, 0x55}, + {0x3983, 0x00}, + {0x3984, 0x2F}, + {0x3985, 0x00}, + {0x3986, 0x23}, + {0x3987, 0x00}, + {0x3988, 0x19}, + {0x3989, 0x00}, + {0x398A, 0x7A}, + {0x398B, 0x00}, + {0x398C, 0x44}, + {0x398D, 0x00}, + {0x398E, 0x35}, + {0x398F, 0x00}, + {0x3990, 0x27}, + {0x3991, 0x00}, + {0x3992, 0xBB}, + {0x3993, 0x00}, + {0x3994, 0x68}, + {0x3995, 0x00}, + {0x3996, 0x53}, + {0x3997, 0x00}, + {0x3998, 0x40}, + {0x3999, 0x00}, + {0x399A, 0x00}, + {0x399B, 0x01}, + {0x399C, 0x00}, + {0x399D, 0x01}, + {0x399E, 0x00}, + {0x399F, 0x01}, + {0x39A0, 0x00}, + {0x39A1, 0x01}, + {0x39A2, 0x70}, + {0x39A3, 0x00}, + {0x39A4, 0x30}, + {0x39A5, 0x00}, + {0x39A6, 0x25}, + {0x39A7, 0x00}, + {0x39A8, 0x20}, + {0x39A9, 0x00}, + {0x39AA, 0xB2}, + {0x39AB, 0x00}, + {0x39AC, 0x80}, + {0x39AD, 0x00}, + {0x39AE, 0x70}, + {0x39AF, 0x00}, + {0x39B0, 0x80}, + {0x39B1, 0x00}, + {0x39B2, 0xB2}, + {0x39B3, 0x00}, + {0x39B4, 0x80}, + {0x39B5, 0x00}, + {0x39B6, 0x70}, + {0x39B7, 0x00}, + {0x39B8, 0x80}, + {0x39B9, 0x00}, + {0x39BA, 0xB2}, + {0x39BB, 0x00}, + {0x39BC, 0x80}, + {0x39BD, 0x00}, + {0x39BE, 0x70}, + {0x39BF, 0x00}, + {0x39C0, 0x80}, + {0x39C1, 0x00}, + {0x39C2, 0x40}, + {0x39C3, 0x00}, + {0x39C4, 0x40}, + {0x39C5, 0x00}, + {0x39C6, 0x40}, + {0x39C7, 0x00}, + {0x39C8, 0x40}, + {0x39C9, 0x00}, + {0x39CA, 0x80}, + {0x39CB, 0x00}, + {0x39CC, 0x80}, + {0x39CD, 0x00}, + {0x39CE, 0x80}, + {0x39CF, 0x00}, + {0x39D0, 0x80}, + {0x39D1, 0x00}, + {0x39D2, 0x80}, + {0x39D3, 0x80}, + {0x39D4, 0x80}, + {0x39E0, 0x01}, + {0x39E1, 0x00}, + {0x39E4, 0x40}, + {0x39E5, 0x01}, + {0x39E6, 0x01}, + {0x39E8, 0x00}, + {0x39E9, 0x01}, + {0x39EA, 0x00}, + {0x39EB, 0x00}, + {0x39EC, 0x01}, + {0x39ED, 0x00}, + {0x39EE, 0x01}, + {0x39F0, 0x03}, + {0x39F1, 0x04}, + {0x39F2, 0x0E}, + {0x39F4, 0x23}, + {0x39F5, 0x00}, + {0x39F6, 0x12}, + {0x39F7, 0x00}, + {0x39F8, 0x0D}, + {0x39F9, 0x00}, + {0x39FA, 0x07}, + {0x39FB, 0x00}, + {0x39FC, 0x3C}, + {0x39FD, 0x00}, + {0x39FE, 0x1B}, + {0x39FF, 0x00}, + {0x3A00, 0x11}, + {0x3A01, 0x00}, + {0x3A02, 0x08}, + {0x3A03, 0x00}, + {0x3A04, 0x4E}, + {0x3A05, 0x00}, + {0x3A06, 0x21}, + {0x3A07, 0x00}, + {0x3A08, 0x14}, + {0x3A09, 0x00}, + {0x3A0A, 0x09}, + {0x3A0B, 0x00}, + {0x3A0C, 0x69}, + {0x3A0D, 0x00}, + {0x3A0E, 0x2C}, + {0x3A0F, 0x00}, + {0x3A10, 0x18}, + {0x3A11, 0x00}, + {0x3A12, 0x0B}, + {0x3A13, 0x00}, + {0x3A14, 0x90}, + {0x3A15, 0x00}, + {0x3A16, 0x3B}, + {0x3A17, 0x00}, + {0x3A18, 0x20}, + {0x3A19, 0x00}, + {0x3A1A, 0x0F}, + {0x3A1B, 0x00}, + {0x3A1C, 0xC9}, + {0x3A1D, 0x00}, + {0x3A1E, 0x51}, + {0x3A1F, 0x00}, + {0x3A20, 0x2B}, + {0x3A21, 0x00}, + {0x3A22, 0x14}, + {0x3A23, 0x00}, + {0x3A24, 0x1A}, + {0x3A25, 0x01}, + {0x3A26, 0x72}, + {0x3A27, 0x00}, + {0x3A28, 0x3C}, + {0x3A29, 0x00}, + {0x3A2A, 0x1B}, + {0x3A2B, 0x00}, + {0x3A2C, 0x8E}, + {0x3A2D, 0x01}, + {0x3A2E, 0xA0}, + {0x3A2F, 0x00}, + {0x3A30, 0x54}, + {0x3A31, 0x00}, + {0x3A32, 0x25}, + {0x3A33, 0x00}, + {0x3A34, 0x31}, + {0x3A35, 0x02}, + {0x3A36, 0xE1}, + {0x3A37, 0x00}, + {0x3A38, 0x76}, + {0x3A39, 0x00}, + {0x3A3A, 0x35}, + {0x3A3B, 0x00}, + {0x3A3C, 0x00}, + {0x3A3D, 0x01}, + {0x3A3E, 0x00}, + {0x3A3F, 0x01}, + {0x3A40, 0x00}, + {0x3A41, 0x01}, + {0x3A42, 0x00}, + {0x3A43, 0x01}, + {0x3A44, 0x80}, + {0x3A45, 0x00}, + {0x3A46, 0x50}, + {0x3A47, 0x00}, + {0x3A48, 0x30}, + {0x3A49, 0x00}, + {0x3A4A, 0x20}, + {0x3A4B, 0x00}, + {0x3A4C, 0x99}, + {0x3A4D, 0x00}, + {0x3A4E, 0x80}, + {0x3A4F, 0x00}, + {0x3A50, 0x80}, + {0x3A51, 0x00}, + {0x3A52, 0x80}, + {0x3A53, 0x00}, + {0x3A54, 0x99}, + {0x3A55, 0x00}, + {0x3A56, 0x80}, + {0x3A57, 0x00}, + {0x3A58, 0x80}, + {0x3A59, 0x00}, + {0x3A5A, 0x80}, + {0x3A5B, 0x00}, + {0x3A5C, 0x99}, + {0x3A5D, 0x00}, + {0x3A5E, 0x80}, + {0x3A5F, 0x00}, + {0x3A60, 0x80}, + {0x3A61, 0x00}, + {0x3A62, 0x80}, + {0x3A63, 0x00}, + {0x3A64, 0x1C}, + {0x3A65, 0x00}, + {0x3A66, 0x13}, + {0x3A67, 0x00}, + {0x3A68, 0x0D}, + {0x3A69, 0x00}, + {0x3A6A, 0x07}, + {0x3A6B, 0x00}, + {0x3A6C, 0x0C}, + {0x3A6D, 0x00}, + {0x3A6E, 0x09}, + {0x3A6F, 0x00}, + {0x3A70, 0x06}, + {0x3A71, 0x00}, + {0x3A72, 0x03}, + {0x3A73, 0x00}, + {0x3A74, 0x1F}, + {0x3A75, 0x00}, + {0x3A76, 0x1B}, + {0x3A77, 0x00}, + {0x3A78, 0x0F}, + {0x3A79, 0x00}, + {0x3A7A, 0x08}, + {0x3A7B, 0x00}, + {0x3A7C, 0x80}, + {0x3A7D, 0x00}, + {0x3A7E, 0x80}, + {0x3A7F, 0x00}, + {0x3A80, 0x80}, + {0x3A81, 0x00}, + {0x3A82, 0x80}, + {0x3A83, 0x00}, + {0x3A84, 0x09}, + {0x3A85, 0x00}, + {0x3A86, 0x04}, + {0x3A87, 0x00}, + {0x3A88, 0x03}, + {0x3A89, 0x00}, + {0x3A8A, 0x01}, + {0x3A8B, 0x00}, + {0x3A8C, 0x19}, + {0x3A8D, 0x01}, + {0x3A8E, 0xD2}, + {0x3A8F, 0x00}, + {0x3A90, 0x8C}, + {0x3A91, 0x00}, + {0x3A92, 0x64}, + {0x3A93, 0x00}, + {0x3A94, 0xFF}, + {0x3A95, 0x00}, + {0x3A96, 0xD2}, + {0x3A97, 0x00}, + {0x3A98, 0x8C}, + {0x3A99, 0x00}, + {0x3A9A, 0x64}, + {0x3A9B, 0x00}, + {0x3A9C, 0x08}, + {0x3A9D, 0x10}, + {0x3A9E, 0x80}, + {0x3A9F, 0x80}, + {0x3AA0, 0x80}, + {0x3AA1, 0x04}, + {0x3AA2, 0x05}, + {0x3AC0, 0x01}, + {0x3AC4, 0x81}, + {0x3AC5, 0x00}, + {0x3AC6, 0x00}, + {0x3AC7, 0x00}, + {0x3AC8, 0x00}, + {0x3AC9, 0x00}, + {0x3ACA, 0x00}, + {0x3ACB, 0x00}, + {0x3ACC, 0x02}, + {0x3ACD, 0x00}, + {0x3ACE, 0x81}, + {0x3ACF, 0x00}, + {0x3AD0, 0x00}, + {0x3AD1, 0x00}, + {0x3AD2, 0xFD}, + {0x3AD3, 0x03}, + {0x3AD4, 0x02}, + {0x3AD5, 0x00}, + {0x3AD6, 0x00}, + {0x3AD7, 0x00}, + {0x3AD8, 0x81}, + {0x3AD9, 0x00}, + {0x3ADA, 0xFD}, + {0x3ADB, 0x03}, + {0x3ADC, 0xFF}, + {0x3ADD, 0x03}, + {0x3ADE, 0x01}, + {0x3ADF, 0x00}, + {0x3AE0, 0x01}, + {0x3AE1, 0x00}, + {0x3AE2, 0x7E}, + {0x3AE3, 0x00}, + {0x3AF4, 0x00}, + {0x3AF6, 0x40}, + {0x3AF7, 0x1E}, + {0x3AF8, 0x01}, + {0x3AFA, 0x63}, + {0x3AFB, 0x09}, + {0x3AFC, 0x11}, + {0x3AFD, 0x09}, + {0x3AFE, 0x00}, + {0x3AFF, 0x00}, + {0x3B00, 0x00}, + {0x3B01, 0x00}, + {0x3B02, 0x84}, + {0x3B03, 0x06}, + {0x3B04, 0x30}, + {0x3B05, 0x06}, + {0x3B06, 0x00}, + {0x3B07, 0x00}, + {0x3B08, 0x00}, + {0x3B09, 0x00}, + {0x3B0A, 0x00}, + {0x3B0B, 0x00}, + {0x3B0C, 0x00}, + {0x3B0D, 0x00}, + {0x3B0E, 0x00}, + {0x3B0F, 0x00}, + {0x3B10, 0x00}, + {0x3B11, 0x00}, + {0x3B12, 0x00}, + {0x3B13, 0x00}, + {0x3B14, 0x00}, + {0x3B15, 0x00}, + {0x3B16, 0x00}, + {0x3B17, 0x00}, + {0x3B18, 0x00}, + {0x3B19, 0x00}, + {0x3B1A, 0x00}, + {0x3B1B, 0x00}, + {0x3B1C, 0x00}, + {0x3B1D, 0x00}, + {0x3B1E, 0x00}, + {0x3B1F, 0x00}, + {0x3B20, 0x00}, + {0x3B21, 0x00}, + {0x3B22, 0x00}, + {0x3B23, 0x00}, + {0x3B24, 0x00}, + {0x3B25, 0x00}, + {0x3B26, 0x00}, + {0x3B27, 0x00}, + {0x3B28, 0x00}, + {0x3B29, 0x00}, + {0x3B2A, 0x00}, + {0x3B2C, 0x00}, + {0x3B2E, 0x00}, + {0x3B30, 0x00}, + {0x3B32, 0x0C}, + {0x4000, 0xD1}, + {0x4001, 0xC0}, + {0x4002, 0xC0}, + {0x4003, 0xB8}, + {0x4004, 0xC0}, + {0x4005, 0xB8}, + {0x4006, 0xB9}, + {0x4007, 0xB7}, + {0x4008, 0xB0}, + {0x4009, 0xAB}, + {0x400A, 0xAC}, + {0x400B, 0xAB}, + {0x400C, 0xA8}, + {0x400D, 0xA6}, + {0x400E, 0xA6}, + {0x400F, 0xA5}, + {0x4010, 0xA2}, + {0x4011, 0xA0}, + {0x4012, 0xA0}, + {0x4013, 0x9F}, + {0x4014, 0xA4}, + {0x4015, 0xA2}, + {0x4016, 0xA2}, + {0x4017, 0x9C}, + {0x4018, 0xA8}, + {0x4019, 0xA6}, + {0x401A, 0xA8}, + {0x401B, 0xAA}, + {0x401C, 0xB0}, + {0x401D, 0xAE}, + {0x401E, 0xAE}, + {0x401F, 0xAE}, + {0x4020, 0xBA}, + {0x4021, 0xAE}, + {0x4022, 0xAF}, + {0x4023, 0xAE}, + {0x4024, 0xC6}, + {0x4025, 0xBD}, + {0x4026, 0xBD}, + {0x4027, 0xBA}, + {0x4028, 0xB0}, + {0x4029, 0xA9}, + {0x402A, 0xAA}, + {0x402B, 0xA8}, + {0x402C, 0x9F}, + {0x402D, 0x9C}, + {0x402E, 0x9C}, + {0x402F, 0x9B}, + {0x4030, 0x93}, + {0x4031, 0x91}, + {0x4032, 0x92}, + {0x4033, 0x91}, + {0x4034, 0x8D}, + {0x4035, 0x8C}, + {0x4036, 0x8C}, + {0x4037, 0x8C}, + {0x4038, 0x8F}, + {0x4039, 0x8E}, + {0x403A, 0x8E}, + {0x403B, 0x8E}, + {0x403C, 0x98}, + {0x403D, 0x96}, + {0x403E, 0x96}, + {0x403F, 0x95}, + {0x4040, 0xA4}, + {0x4041, 0xA0}, + {0x4042, 0xA0}, + {0x4043, 0x9E}, + {0x4044, 0xB3}, + {0x4045, 0xAE}, + {0x4046, 0xAF}, + {0x4047, 0xAB}, + {0x4048, 0xC2}, + {0x4049, 0xB7}, + {0x404A, 0xB8}, + {0x404B, 0xB5}, + {0x404C, 0xAB}, + {0x404D, 0xA4}, + {0x404E, 0xA5}, + {0x404F, 0xA3}, + {0x4050, 0x99}, + {0x4051, 0x96}, + {0x4052, 0x96}, + {0x4053, 0x96}, + {0x4054, 0x8B}, + {0x4055, 0x8A}, + {0x4056, 0x8A}, + {0x4057, 0x8A}, + {0x4058, 0x82}, + {0x4059, 0x81}, + {0x405A, 0x81}, + {0x405B, 0x81}, + {0x405C, 0x85}, + {0x405D, 0x86}, + {0x405E, 0x85}, + {0x405F, 0x85}, + {0x4060, 0x90}, + {0x4061, 0x90}, + {0x4062, 0x8F}, + {0x4063, 0x8F}, + {0x4064, 0x9D}, + {0x4065, 0x9B}, + {0x4066, 0x9B}, + {0x4067, 0x9A}, + {0x4068, 0xAF}, + {0x4069, 0xAA}, + {0x406A, 0xAC}, + {0x406B, 0xAA}, + {0x406C, 0xC2}, + {0x406D, 0xB7}, + {0x406E, 0xB8}, + {0x406F, 0xB5}, + {0x4070, 0xAB}, + {0x4071, 0xA4}, + {0x4072, 0xA4}, + {0x4073, 0xA3}, + {0x4074, 0x99}, + {0x4075, 0x96}, + {0x4076, 0x96}, + {0x4077, 0x96}, + {0x4078, 0x8B}, + {0x4079, 0x8A}, + {0x407A, 0x8A}, + {0x407B, 0x8A}, + {0x407C, 0x82}, + {0x407D, 0x82}, + {0x407E, 0x82}, + {0x407F, 0x82}, + {0x4080, 0x85}, + {0x4081, 0x86}, + {0x4082, 0x86}, + {0x4083, 0x86}, + {0x4084, 0x90}, + {0x4085, 0x90}, + {0x4086, 0x8F}, + {0x4087, 0x8F}, + {0x4088, 0x9D}, + {0x4089, 0x9B}, + {0x408A, 0x9B}, + {0x408B, 0x99}, + {0x408C, 0xAE}, + {0x408D, 0xAA}, + {0x408E, 0xAA}, + {0x408F, 0xA7}, + {0x4090, 0xC7}, + {0x4091, 0xBA}, + {0x4092, 0xBC}, + {0x4093, 0xB9}, + {0x4094, 0xB1}, + {0x4095, 0xA8}, + {0x4096, 0xA8}, + {0x4097, 0xA7}, + {0x4098, 0x9F}, + {0x4099, 0x9B}, + {0x409A, 0x9B}, + {0x409B, 0x9B}, + {0x409C, 0x93}, + {0x409D, 0x91}, + {0x409E, 0x91}, + {0x409F, 0x91}, + {0x40A0, 0x8D}, + {0x40A1, 0x8C}, + {0x40A2, 0x8C}, + {0x40A3, 0x8C}, + {0x40A4, 0x8E}, + {0x40A5, 0x8E}, + {0x40A6, 0x8D}, + {0x40A7, 0x8D}, + {0x40A8, 0x96}, + {0x40A9, 0x95}, + {0x40AA, 0x95}, + {0x40AB, 0x94}, + {0x40AC, 0xA2}, + {0x40AD, 0x9F}, + {0x40AE, 0x9F}, + {0x40AF, 0x9D}, + {0x40B0, 0xB1}, + {0x40B1, 0xAC}, + {0x40B2, 0xAB}, + {0x40B3, 0xAA}, + {0x40B4, 0xD3}, + {0x40B5, 0xBC}, + {0x40B6, 0xBD}, + {0x40B7, 0xBC}, + {0x40B8, 0xC1}, + {0x40B9, 0xB7}, + {0x40BA, 0xB7}, + {0x40BB, 0xB5}, + {0x40BC, 0xB0}, + {0x40BD, 0xAA}, + {0x40BE, 0xAA}, + {0x40BF, 0xAA}, + {0x40C0, 0xA8}, + {0x40C1, 0xA4}, + {0x40C2, 0xA4}, + {0x40C3, 0xA4}, + {0x40C4, 0xA2}, + {0x40C5, 0x9F}, + {0x40C6, 0x9F}, + {0x40C7, 0x9F}, + {0x40C8, 0xA3}, + {0x40C9, 0xA0}, + {0x40CA, 0xA0}, + {0x40CB, 0xA0}, + {0x40CC, 0xA6}, + {0x40CD, 0xA3}, + {0x40CE, 0xA3}, + {0x40CF, 0xA2}, + {0x40D0, 0xAF}, + {0x40D1, 0xAB}, + {0x40D2, 0xAA}, + {0x40D3, 0xA8}, + {0x40D4, 0xBA}, + {0x40D5, 0xAE}, + {0x40D6, 0xAE}, + {0x40D7, 0xAB}, + {0x4100, 0xBD}, + {0x4101, 0xBA}, + {0x4102, 0xBD}, + {0x4103, 0xB7}, + {0x4104, 0xB7}, + {0x4105, 0xB7}, + {0x4106, 0xB8}, + {0x4107, 0xB5}, + {0x4108, 0xAB}, + {0x4109, 0xAA}, + {0x410A, 0xAC}, + {0x410B, 0xAB}, + {0x410C, 0xA4}, + {0x410D, 0xA5}, + {0x410E, 0xA5}, + {0x410F, 0xA4}, + {0x4110, 0x9F}, + {0x4111, 0xA0}, + {0x4112, 0xA0}, + {0x4113, 0x9F}, + {0x4114, 0xA0}, + {0x4115, 0xA0}, + {0x4116, 0xA0}, + {0x4117, 0x9F}, + {0x4118, 0xA1}, + {0x4119, 0xA1}, + {0x411A, 0xA1}, + {0x411B, 0xA0}, + {0x411C, 0xA7}, + {0x411D, 0xA6}, + {0x411E, 0xA6}, + {0x411F, 0xA6}, + {0x4120, 0xA7}, + {0x4121, 0xA6}, + {0x4122, 0xA6}, + {0x4123, 0xA3}, + {0x4124, 0xB9}, + {0x4125, 0xB9}, + {0x4126, 0xBA}, + {0x4127, 0xB8}, + {0x4128, 0xA6}, + {0x4129, 0xA7}, + {0x412A, 0xA7}, + {0x412B, 0xA6}, + {0x412C, 0x9B}, + {0x412D, 0x9B}, + {0x412E, 0x9B}, + {0x412F, 0x9B}, + {0x4130, 0x91}, + {0x4131, 0x92}, + {0x4132, 0x92}, + {0x4133, 0x91}, + {0x4134, 0x8C}, + {0x4135, 0x8C}, + {0x4136, 0x8C}, + {0x4137, 0x8C}, + {0x4138, 0x8D}, + {0x4139, 0x8D}, + {0x413A, 0x8D}, + {0x413B, 0x8D}, + {0x413C, 0x93}, + {0x413D, 0x93}, + {0x413E, 0x93}, + {0x413F, 0x92}, + {0x4140, 0x9A}, + {0x4141, 0x9A}, + {0x4142, 0x9A}, + {0x4143, 0x99}, + {0x4144, 0xA7}, + {0x4145, 0xA5}, + {0x4146, 0xA6}, + {0x4147, 0xA6}, + {0x4148, 0xB8}, + {0x4149, 0xB4}, + {0x414A, 0xB4}, + {0x414B, 0xB3}, + {0x414C, 0xA3}, + {0x414D, 0xA2}, + {0x414E, 0xA3}, + {0x414F, 0xA2}, + {0x4150, 0x96}, + {0x4151, 0x96}, + {0x4152, 0x96}, + {0x4153, 0x96}, + {0x4154, 0x8A}, + {0x4155, 0x8A}, + {0x4156, 0x8A}, + {0x4157, 0x8A}, + {0x4158, 0x82}, + {0x4159, 0x82}, + {0x415A, 0x82}, + {0x415B, 0x82}, + {0x415C, 0x84}, + {0x415D, 0x85}, + {0x415E, 0x84}, + {0x415F, 0x84}, + {0x4160, 0x8D}, + {0x4161, 0x8D}, + {0x4162, 0x8D}, + {0x4163, 0x8D}, + {0x4164, 0x96}, + {0x4165, 0x96}, + {0x4166, 0x96}, + {0x4167, 0x95}, + {0x4168, 0xA5}, + {0x4169, 0xA2}, + {0x416A, 0xA3}, + {0x416B, 0xA2}, + {0x416C, 0xB7}, + {0x416D, 0xB3}, + {0x416E, 0xB5}, + {0x416F, 0xB4}, + {0x4170, 0xA4}, + {0x4171, 0xA2}, + {0x4172, 0xA3}, + {0x4173, 0xA2}, + {0x4174, 0x97}, + {0x4175, 0x96}, + {0x4176, 0x96}, + {0x4177, 0x96}, + {0x4178, 0x8B}, + {0x4179, 0x8A}, + {0x417A, 0x8A}, + {0x417B, 0x8A}, + {0x417C, 0x81}, + {0x417D, 0x81}, + {0x417E, 0x81}, + {0x417F, 0x81}, + {0x4180, 0x84}, + {0x4181, 0x84}, + {0x4182, 0x84}, + {0x4183, 0x84}, + {0x4184, 0x8C}, + {0x4185, 0x8D}, + {0x4186, 0x8D}, + {0x4187, 0x8D}, + {0x4188, 0x95}, + {0x4189, 0x96}, + {0x418A, 0x96}, + {0x418B, 0x95}, + {0x418C, 0xA1}, + {0x418D, 0xA1}, + {0x418E, 0xA1}, + {0x418F, 0xA0}, + {0x4190, 0xBC}, + {0x4191, 0xB8}, + {0x4192, 0xB8}, + {0x4193, 0xB9}, + {0x4194, 0xA8}, + {0x4195, 0xA5}, + {0x4196, 0xA6}, + {0x4197, 0xA5}, + {0x4198, 0x9C}, + {0x4199, 0x9A}, + {0x419A, 0x9A}, + {0x419B, 0x9A}, + {0x419C, 0x91}, + {0x419D, 0x91}, + {0x419E, 0x91}, + {0x419F, 0x91}, + {0x41A0, 0x8B}, + {0x41A1, 0x8B}, + {0x41A2, 0x8B}, + {0x41A3, 0x8B}, + {0x41A4, 0x8C}, + {0x41A5, 0x8C}, + {0x41A6, 0x8C}, + {0x41A7, 0x8C}, + {0x41A8, 0x91}, + {0x41A9, 0x92}, + {0x41AA, 0x91}, + {0x41AB, 0x91}, + {0x41AC, 0x98}, + {0x41AD, 0x99}, + {0x41AE, 0x99}, + {0x41AF, 0x98}, + {0x41B0, 0xA3}, + {0x41B1, 0xA3}, + {0x41B2, 0xA3}, + {0x41B3, 0xA2}, + {0x41B4, 0xC1}, + {0x41B5, 0xB8}, + {0x41B6, 0xB9}, + {0x41B7, 0xBA}, + {0x41B8, 0xB8}, + {0x41B9, 0xB4}, + {0x41BA, 0xB4}, + {0x41BB, 0xB4}, + {0x41BC, 0xAA}, + {0x41BD, 0xA7}, + {0x41BE, 0xA7}, + {0x41BF, 0xA8}, + {0x41C0, 0xA4}, + {0x41C1, 0xA2}, + {0x41C2, 0xA2}, + {0x41C3, 0xA3}, + {0x41C4, 0x9E}, + {0x41C5, 0x9D}, + {0x41C6, 0x9D}, + {0x41C7, 0x9D}, + {0x41C8, 0x9E}, + {0x41C9, 0x9D}, + {0x41CA, 0x9D}, + {0x41CB, 0x9D}, + {0x41CC, 0x9E}, + {0x41CD, 0x9E}, + {0x41CE, 0x9E}, + {0x41CF, 0x9E}, + {0x41D0, 0xA3}, + {0x41D1, 0xA3}, + {0x41D2, 0xA2}, + {0x41D3, 0xA1}, + {0x41D4, 0xA7}, + {0x41D5, 0xA7}, + {0x41D6, 0xA7}, + {0x41D7, 0xA3}, + {0x4200, 0xCE}, + {0x4201, 0xC0}, + {0x4202, 0xC1}, + {0x4203, 0xB9}, + {0x4204, 0xC3}, + {0x4205, 0xB9}, + {0x4206, 0xBC}, + {0x4207, 0xBD}, + {0x4208, 0xB3}, + {0x4209, 0xAE}, + {0x420A, 0xAF}, + {0x420B, 0xAE}, + {0x420C, 0xAA}, + {0x420D, 0xA8}, + {0x420E, 0xA8}, + {0x420F, 0xA6}, + {0x4210, 0xA4}, + {0x4211, 0xA2}, + {0x4212, 0xA2}, + {0x4213, 0xA0}, + {0x4214, 0xA4}, + {0x4215, 0xA3}, + {0x4216, 0xA2}, + {0x4217, 0xA0}, + {0x4218, 0xA7}, + {0x4219, 0xA5}, + {0x421A, 0xA3}, + {0x421B, 0xA1}, + {0x421C, 0xB0}, + {0x421D, 0xA8}, + {0x421E, 0xA8}, + {0x421F, 0xA6}, + {0x4220, 0xB4}, + {0x4221, 0xAA}, + {0x4222, 0xA5}, + {0x4223, 0xA3}, + {0x4224, 0xC7}, + {0x4225, 0xBC}, + {0x4226, 0xBE}, + {0x4227, 0xBC}, + {0x4228, 0xB0}, + {0x4229, 0xA9}, + {0x422A, 0xA9}, + {0x422B, 0xA8}, + {0x422C, 0xA0}, + {0x422D, 0x9D}, + {0x422E, 0x9D}, + {0x422F, 0x9C}, + {0x4230, 0x94}, + {0x4231, 0x93}, + {0x4232, 0x93}, + {0x4233, 0x92}, + {0x4234, 0x8E}, + {0x4235, 0x8D}, + {0x4236, 0x8D}, + {0x4237, 0x8C}, + {0x4238, 0x8F}, + {0x4239, 0x8E}, + {0x423A, 0x8E}, + {0x423B, 0x8D}, + {0x423C, 0x96}, + {0x423D, 0x94}, + {0x423E, 0x94}, + {0x423F, 0x92}, + {0x4240, 0xA1}, + {0x4241, 0x9C}, + {0x4242, 0x9C}, + {0x4243, 0x99}, + {0x4244, 0xB0}, + {0x4245, 0xA8}, + {0x4246, 0xAB}, + {0x4247, 0xA7}, + {0x4248, 0xC3}, + {0x4249, 0xB7}, + {0x424A, 0xB7}, + {0x424B, 0xBC}, + {0x424C, 0xAB}, + {0x424D, 0xA4}, + {0x424E, 0xA5}, + {0x424F, 0xA5}, + {0x4250, 0x9A}, + {0x4251, 0x97}, + {0x4252, 0x97}, + {0x4253, 0x98}, + {0x4254, 0x8C}, + {0x4255, 0x8B}, + {0x4256, 0x8B}, + {0x4257, 0x8B}, + {0x4258, 0x82}, + {0x4259, 0x82}, + {0x425A, 0x82}, + {0x425B, 0x82}, + {0x425C, 0x85}, + {0x425D, 0x85}, + {0x425E, 0x85}, + {0x425F, 0x84}, + {0x4260, 0x8F}, + {0x4261, 0x8E}, + {0x4262, 0x8E}, + {0x4263, 0x8D}, + {0x4264, 0x9B}, + {0x4265, 0x98}, + {0x4266, 0x98}, + {0x4267, 0x95}, + {0x4268, 0xAE}, + {0x4269, 0xA5}, + {0x426A, 0xA7}, + {0x426B, 0xA2}, + {0x426C, 0xC2}, + {0x426D, 0xB7}, + {0x426E, 0xB8}, + {0x426F, 0xB9}, + {0x4270, 0xAA}, + {0x4271, 0xA4}, + {0x4272, 0xA4}, + {0x4273, 0xA5}, + {0x4274, 0x99}, + {0x4275, 0x96}, + {0x4276, 0x97}, + {0x4277, 0x98}, + {0x4278, 0x8B}, + {0x4279, 0x8A}, + {0x427A, 0x8A}, + {0x427B, 0x8B}, + {0x427C, 0x81}, + {0x427D, 0x81}, + {0x427E, 0x81}, + {0x427F, 0x82}, + {0x4280, 0x84}, + {0x4281, 0x84}, + {0x4282, 0x84}, + {0x4283, 0x84}, + {0x4284, 0x8E}, + {0x4285, 0x8E}, + {0x4286, 0x8D}, + {0x4287, 0x8C}, + {0x4288, 0x9A}, + {0x4289, 0x97}, + {0x428A, 0x97}, + {0x428B, 0x95}, + {0x428C, 0xAA}, + {0x428D, 0xA3}, + {0x428E, 0xA3}, + {0x428F, 0xA2}, + {0x4290, 0xC7}, + {0x4291, 0xBA}, + {0x4292, 0xC0}, + {0x4293, 0xC3}, + {0x4294, 0xB0}, + {0x4295, 0xA7}, + {0x4296, 0xA7}, + {0x4297, 0xA9}, + {0x4298, 0x9F}, + {0x4299, 0x9B}, + {0x429A, 0x9B}, + {0x429B, 0x9D}, + {0x429C, 0x93}, + {0x429D, 0x91}, + {0x429E, 0x91}, + {0x429F, 0x92}, + {0x42A0, 0x8C}, + {0x42A1, 0x8B}, + {0x42A2, 0x8B}, + {0x42A3, 0x8C}, + {0x42A4, 0x8D}, + {0x42A5, 0x8C}, + {0x42A6, 0x8C}, + {0x42A7, 0x8C}, + {0x42A8, 0x94}, + {0x42A9, 0x93}, + {0x42AA, 0x92}, + {0x42AB, 0x91}, + {0x42AC, 0x9E}, + {0x42AD, 0x9B}, + {0x42AE, 0x9B}, + {0x42AF, 0x98}, + {0x42B0, 0xAC}, + {0x42B1, 0xA6}, + {0x42B2, 0xA6}, + {0x42B3, 0xA2}, + {0x42B4, 0xCE}, + {0x42B5, 0xBA}, + {0x42B6, 0xBC}, + {0x42B7, 0xB7}, + {0x42B8, 0xC5}, + {0x42B9, 0xB5}, + {0x42BA, 0xBA}, + {0x42BB, 0xC0}, + {0x42BC, 0xB1}, + {0x42BD, 0xA8}, + {0x42BE, 0xAE}, + {0x42BF, 0xAF}, + {0x42C0, 0xA7}, + {0x42C1, 0xA3}, + {0x42C2, 0xA3}, + {0x42C3, 0xA5}, + {0x42C4, 0xA0}, + {0x42C5, 0x9D}, + {0x42C6, 0x9D}, + {0x42C7, 0x9F}, + {0x42C8, 0xA0}, + {0x42C9, 0x9E}, + {0x42CA, 0x9E}, + {0x42CB, 0x9F}, + {0x42CC, 0xA2}, + {0x42CD, 0xA0}, + {0x42CE, 0xA0}, + {0x42CF, 0xA0}, + {0x42D0, 0xA8}, + {0x42D1, 0xA5}, + {0x42D2, 0xA5}, + {0x42D3, 0xA2}, + {0x42D4, 0xB3}, + {0x42D5, 0xAA}, + {0x42D6, 0xAB}, + {0x42D7, 0xA3}, + {0x42D8, 0x00}, + {0x42D9, 0x00}, + {0x4300, 0xA2}, + {0x4301, 0xAE}, + {0x4302, 0xAD}, + {0x4303, 0xB5}, + {0x4304, 0x95}, + {0x4305, 0x9A}, + {0x4306, 0x98}, + {0x4307, 0x9B}, + {0x4308, 0x8D}, + {0x4309, 0x90}, + {0x430A, 0x8F}, + {0x430B, 0x91}, + {0x430C, 0x86}, + {0x430D, 0x88}, + {0x430E, 0x87}, + {0x430F, 0x89}, + {0x4310, 0x86}, + {0x4311, 0x87}, + {0x4312, 0x86}, + {0x4313, 0x88}, + {0x4314, 0x89}, + {0x4315, 0x88}, + {0x4316, 0x88}, + {0x4317, 0x8E}, + {0x4318, 0x90}, + {0x4319, 0x8F}, + {0x431A, 0x8C}, + {0x431B, 0x8C}, + {0x431C, 0x9C}, + {0x431D, 0x99}, + {0x431E, 0x98}, + {0x431F, 0x99}, + {0x4320, 0xAB}, + {0x4321, 0xB0}, + {0x4322, 0xAD}, + {0x4323, 0xAF}, + {0x4324, 0x9B}, + {0x4325, 0x9F}, + {0x4326, 0x9E}, + {0x4327, 0xA1}, + {0x4328, 0x8E}, + {0x4329, 0x91}, + {0x432A, 0x90}, + {0x432B, 0x93}, + {0x432C, 0x86}, + {0x432D, 0x88}, + {0x432E, 0x87}, + {0x432F, 0x89}, + {0x4330, 0x82}, + {0x4331, 0x84}, + {0x4332, 0x83}, + {0x4333, 0x84}, + {0x4334, 0x82}, + {0x4335, 0x82}, + {0x4336, 0x82}, + {0x4337, 0x83}, + {0x4338, 0x85}, + {0x4339, 0x84}, + {0x433A, 0x84}, + {0x433B, 0x85}, + {0x433C, 0x8A}, + {0x433D, 0x89}, + {0x433E, 0x88}, + {0x433F, 0x89}, + {0x4340, 0x93}, + {0x4341, 0x91}, + {0x4342, 0x91}, + {0x4343, 0x93}, + {0x4344, 0xA0}, + {0x4345, 0x9E}, + {0x4346, 0x9D}, + {0x4347, 0xA1}, + {0x4348, 0x95}, + {0x4349, 0x9B}, + {0x434A, 0x9A}, + {0x434B, 0x9C}, + {0x434C, 0x8A}, + {0x434D, 0x8D}, + {0x434E, 0x8C}, + {0x434F, 0x8D}, + {0x4350, 0x83}, + {0x4351, 0x85}, + {0x4352, 0x84}, + {0x4353, 0x85}, + {0x4354, 0x80}, + {0x4355, 0x81}, + {0x4356, 0x81}, + {0x4357, 0x81}, + {0x4358, 0x80}, + {0x4359, 0x80}, + {0x435A, 0x80}, + {0x435B, 0x80}, + {0x435C, 0x82}, + {0x435D, 0x81}, + {0x435E, 0x81}, + {0x435F, 0x81}, + {0x4360, 0x85}, + {0x4361, 0x84}, + {0x4362, 0x84}, + {0x4363, 0x85}, + {0x4364, 0x8D}, + {0x4365, 0x8B}, + {0x4366, 0x8B}, + {0x4367, 0x8D}, + {0x4368, 0x98}, + {0x4369, 0x98}, + {0x436A, 0x95}, + {0x436B, 0x98}, + {0x436C, 0x95}, + {0x436D, 0x9A}, + {0x436E, 0x99}, + {0x436F, 0x9A}, + {0x4370, 0x8A}, + {0x4371, 0x8D}, + {0x4372, 0x8C}, + {0x4373, 0x8C}, + {0x4374, 0x83}, + {0x4375, 0x85}, + {0x4376, 0x84}, + {0x4377, 0x84}, + {0x4378, 0x80}, + {0x4379, 0x80}, + {0x437A, 0x80}, + {0x437B, 0x80}, + {0x437C, 0x7F}, + {0x437D, 0x7F}, + {0x437E, 0x7F}, + {0x437F, 0x7F}, + {0x4380, 0x81}, + {0x4381, 0x80}, + {0x4382, 0x80}, + {0x4383, 0x81}, + {0x4384, 0x84}, + {0x4385, 0x83}, + {0x4386, 0x83}, + {0x4387, 0x84}, + {0x4388, 0x8B}, + {0x4389, 0x8A}, + {0x438A, 0x8A}, + {0x438B, 0x8C}, + {0x438C, 0x97}, + {0x438D, 0x96}, + {0x438E, 0x96}, + {0x438F, 0x99}, + {0x4390, 0x99}, + {0x4391, 0x9F}, + {0x4392, 0x9E}, + {0x4393, 0x9D}, + {0x4394, 0x8D}, + {0x4395, 0x90}, + {0x4396, 0x90}, + {0x4397, 0x8F}, + {0x4398, 0x85}, + {0x4399, 0x87}, + {0x439A, 0x87}, + {0x439B, 0x86}, + {0x439C, 0x81}, + {0x439D, 0x83}, + {0x439E, 0x82}, + {0x439F, 0x82}, + {0x43A0, 0x80}, + {0x43A1, 0x81}, + {0x43A2, 0x81}, + {0x43A3, 0x81}, + {0x43A4, 0x82}, + {0x43A5, 0x82}, + {0x43A6, 0x82}, + {0x43A7, 0x82}, + {0x43A8, 0x86}, + {0x43A9, 0x85}, + {0x43AA, 0x85}, + {0x43AB, 0x87}, + {0x43AC, 0x8D}, + {0x43AD, 0x8D}, + {0x43AE, 0x8D}, + {0x43AF, 0x90}, + {0x43B0, 0x9A}, + {0x43B1, 0x9A}, + {0x43B2, 0x9B}, + {0x43B3, 0x9D}, + {0x43B4, 0xA0}, + {0x43B5, 0xAD}, + {0x43B6, 0xAC}, + {0x43B7, 0xAA}, + {0x43B8, 0x93}, + {0x43B9, 0x97}, + {0x43BA, 0x97}, + {0x43BB, 0x96}, + {0x43BC, 0x8B}, + {0x43BD, 0x8E}, + {0x43BE, 0x8E}, + {0x43BF, 0x8C}, + {0x43C0, 0x83}, + {0x43C1, 0x85}, + {0x43C2, 0x85}, + {0x43C3, 0x84}, + {0x43C4, 0x82}, + {0x43C5, 0x84}, + {0x43C6, 0x83}, + {0x43C7, 0x83}, + {0x43C8, 0x83}, + {0x43C9, 0x84}, + {0x43CA, 0x84}, + {0x43CB, 0x85}, + {0x43CC, 0x8A}, + {0x43CD, 0x8A}, + {0x43CE, 0x8A}, + {0x43CF, 0x8C}, + {0x43D0, 0x92}, + {0x43D1, 0x93}, + {0x43D2, 0x93}, + {0x43D3, 0x96}, + {0x43D4, 0x9F}, + {0x43D5, 0xA6}, + {0x43D6, 0xA5}, + {0x43D7, 0xAA}, + {0x4400, 0xA1}, + {0x4401, 0xAB}, + {0x4402, 0xA7}, + {0x4403, 0xB0}, + {0x4404, 0x91}, + {0x4405, 0x96}, + {0x4406, 0x94}, + {0x4407, 0x99}, + {0x4408, 0x8A}, + {0x4409, 0x8E}, + {0x440A, 0x8C}, + {0x440B, 0x8F}, + {0x440C, 0x85}, + {0x440D, 0x86}, + {0x440E, 0x86}, + {0x440F, 0x88}, + {0x4410, 0x85}, + {0x4411, 0x86}, + {0x4412, 0x85}, + {0x4413, 0x87}, + {0x4414, 0x88}, + {0x4415, 0x87}, + {0x4416, 0x87}, + {0x4417, 0x89}, + {0x4418, 0x91}, + {0x4419, 0x8F}, + {0x441A, 0x8F}, + {0x441B, 0x90}, + {0x441C, 0x9C}, + {0x441D, 0x9B}, + {0x441E, 0x9A}, + {0x441F, 0x9A}, + {0x4420, 0xB3}, + {0x4421, 0xB1}, + {0x4422, 0xB0}, + {0x4423, 0xB2}, + {0x4424, 0x96}, + {0x4425, 0x9C}, + {0x4426, 0x9A}, + {0x4427, 0x9E}, + {0x4428, 0x8B}, + {0x4429, 0x8F}, + {0x442A, 0x8E}, + {0x442B, 0x91}, + {0x442C, 0x84}, + {0x442D, 0x87}, + {0x442E, 0x86}, + {0x442F, 0x88}, + {0x4430, 0x82}, + {0x4431, 0x83}, + {0x4432, 0x82}, + {0x4433, 0x84}, + {0x4434, 0x82}, + {0x4435, 0x82}, + {0x4436, 0x82}, + {0x4437, 0x83}, + {0x4438, 0x84}, + {0x4439, 0x84}, + {0x443A, 0x84}, + {0x443B, 0x84}, + {0x443C, 0x8B}, + {0x443D, 0x89}, + {0x443E, 0x89}, + {0x443F, 0x89}, + {0x4440, 0x95}, + {0x4441, 0x93}, + {0x4442, 0x93}, + {0x4443, 0x93}, + {0x4444, 0xA2}, + {0x4445, 0xA2}, + {0x4446, 0xA1}, + {0x4447, 0xA0}, + {0x4448, 0x8F}, + {0x4449, 0x97}, + {0x444A, 0x97}, + {0x444B, 0x98}, + {0x444C, 0x87}, + {0x444D, 0x8B}, + {0x444E, 0x8A}, + {0x444F, 0x8B}, + {0x4450, 0x81}, + {0x4451, 0x83}, + {0x4452, 0x83}, + {0x4453, 0x84}, + {0x4454, 0x7F}, + {0x4455, 0x80}, + {0x4456, 0x80}, + {0x4457, 0x81}, + {0x4458, 0x80}, + {0x4459, 0x80}, + {0x445A, 0x80}, + {0x445B, 0x80}, + {0x445C, 0x82}, + {0x445D, 0x81}, + {0x445E, 0x81}, + {0x445F, 0x81}, + {0x4460, 0x87}, + {0x4461, 0x85}, + {0x4462, 0x85}, + {0x4463, 0x86}, + {0x4464, 0x90}, + {0x4465, 0x8E}, + {0x4466, 0x8E}, + {0x4467, 0x8E}, + {0x4468, 0x9B}, + {0x4469, 0x9C}, + {0x446A, 0x9A}, + {0x446B, 0x9A}, + {0x446C, 0x91}, + {0x446D, 0x97}, + {0x446E, 0x95}, + {0x446F, 0x95}, + {0x4470, 0x87}, + {0x4471, 0x8A}, + {0x4472, 0x8A}, + {0x4473, 0x89}, + {0x4474, 0x81}, + {0x4475, 0x83}, + {0x4476, 0x83}, + {0x4477, 0x83}, + {0x4478, 0x7F}, + {0x4479, 0x80}, + {0x447A, 0x80}, + {0x447B, 0x80}, + {0x447C, 0x80}, + {0x447D, 0x80}, + {0x447E, 0x80}, + {0x447F, 0x7F}, + {0x4480, 0x81}, + {0x4481, 0x81}, + {0x4482, 0x81}, + {0x4483, 0x81}, + {0x4484, 0x85}, + {0x4485, 0x85}, + {0x4486, 0x85}, + {0x4487, 0x85}, + {0x4488, 0x8E}, + {0x4489, 0x8D}, + {0x448A, 0x8D}, + {0x448B, 0x8E}, + {0x448C, 0x9D}, + {0x448D, 0x9C}, + {0x448E, 0x9C}, + {0x448F, 0x9C}, + {0x4490, 0x94}, + {0x4491, 0x9B}, + {0x4492, 0x9A}, + {0x4493, 0x97}, + {0x4494, 0x8A}, + {0x4495, 0x8E}, + {0x4496, 0x8E}, + {0x4497, 0x8C}, + {0x4498, 0x84}, + {0x4499, 0x86}, + {0x449A, 0x86}, + {0x449B, 0x84}, + {0x449C, 0x81}, + {0x449D, 0x83}, + {0x449E, 0x83}, + {0x449F, 0x81}, + {0x44A0, 0x81}, + {0x44A1, 0x82}, + {0x44A2, 0x82}, + {0x44A3, 0x81}, + {0x44A4, 0x83}, + {0x44A5, 0x83}, + {0x44A6, 0x83}, + {0x44A7, 0x83}, + {0x44A8, 0x88}, + {0x44A9, 0x88}, + {0x44AA, 0x88}, + {0x44AB, 0x88}, + {0x44AC, 0x91}, + {0x44AD, 0x91}, + {0x44AE, 0x91}, + {0x44AF, 0x92}, + {0x44B0, 0xA0}, + {0x44B1, 0xA0}, + {0x44B2, 0xA0}, + {0x44B3, 0xA0}, + {0x44B4, 0x9E}, + {0x44B5, 0xA9}, + {0x44B6, 0xA8}, + {0x44B7, 0xA3}, + {0x44B8, 0x90}, + {0x44B9, 0x95}, + {0x44BA, 0x95}, + {0x44BB, 0x92}, + {0x44BC, 0x8A}, + {0x44BD, 0x8E}, + {0x44BE, 0x8E}, + {0x44BF, 0x8B}, + {0x44C0, 0x84}, + {0x44C1, 0x86}, + {0x44C2, 0x86}, + {0x44C3, 0x84}, + {0x44C4, 0x84}, + {0x44C5, 0x85}, + {0x44C6, 0x85}, + {0x44C7, 0x84}, + {0x44C8, 0x86}, + {0x44C9, 0x87}, + {0x44CA, 0x87}, + {0x44CB, 0x86}, + {0x44CC, 0x8D}, + {0x44CD, 0x8E}, + {0x44CE, 0x8E}, + {0x44CF, 0x8D}, + {0x44D0, 0x98}, + {0x44D1, 0x98}, + {0x44D2, 0x99}, + {0x44D3, 0x9A}, + {0x44D4, 0xA9}, + {0x44D5, 0xAA}, + {0x44D6, 0xAA}, + {0x44D7, 0xAD}, + {0x4500, 0x9F}, + {0x4501, 0xA8}, + {0x4502, 0xA5}, + {0x4503, 0xAF}, + {0x4504, 0x8F}, + {0x4505, 0x96}, + {0x4506, 0x92}, + {0x4507, 0x94}, + {0x4508, 0x89}, + {0x4509, 0x8D}, + {0x450A, 0x8A}, + {0x450B, 0x8E}, + {0x450C, 0x84}, + {0x450D, 0x85}, + {0x450E, 0x84}, + {0x450F, 0x87}, + {0x4510, 0x84}, + {0x4511, 0x85}, + {0x4512, 0x84}, + {0x4513, 0x86}, + {0x4514, 0x87}, + {0x4515, 0x86}, + {0x4516, 0x86}, + {0x4517, 0x88}, + {0x4518, 0x8F}, + {0x4519, 0x8D}, + {0x451A, 0x8D}, + {0x451B, 0x8F}, + {0x451C, 0x9A}, + {0x451D, 0x9A}, + {0x451E, 0x98}, + {0x451F, 0x9A}, + {0x4520, 0xAF}, + {0x4521, 0xAF}, + {0x4522, 0xB2}, + {0x4523, 0xB1}, + {0x4524, 0x95}, + {0x4525, 0x9B}, + {0x4526, 0x97}, + {0x4527, 0x9C}, + {0x4528, 0x8A}, + {0x4529, 0x8E}, + {0x452A, 0x8D}, + {0x452B, 0x90}, + {0x452C, 0x84}, + {0x452D, 0x86}, + {0x452E, 0x85}, + {0x452F, 0x87}, + {0x4530, 0x81}, + {0x4531, 0x82}, + {0x4532, 0x82}, + {0x4533, 0x83}, + {0x4534, 0x81}, + {0x4535, 0x81}, + {0x4536, 0x81}, + {0x4537, 0x82}, + {0x4538, 0x84}, + {0x4539, 0x83}, + {0x453A, 0x83}, + {0x453B, 0x84}, + {0x453C, 0x8A}, + {0x453D, 0x88}, + {0x453E, 0x88}, + {0x453F, 0x89}, + {0x4540, 0x94}, + {0x4541, 0x92}, + {0x4542, 0x91}, + {0x4543, 0x92}, + {0x4544, 0xA1}, + {0x4545, 0xA0}, + {0x4546, 0x9C}, + {0x4547, 0x9D}, + {0x4548, 0x8F}, + {0x4549, 0x96}, + {0x454A, 0x95}, + {0x454B, 0x92}, + {0x454C, 0x87}, + {0x454D, 0x8A}, + {0x454E, 0x89}, + {0x454F, 0x8A}, + {0x4550, 0x81}, + {0x4551, 0x83}, + {0x4552, 0x82}, + {0x4553, 0x83}, + {0x4554, 0x7F}, + {0x4555, 0x80}, + {0x4556, 0x80}, + {0x4557, 0x81}, + {0x4558, 0x7F}, + {0x4559, 0x80}, + {0x455A, 0x7F}, + {0x455B, 0x80}, + {0x455C, 0x81}, + {0x455D, 0x81}, + {0x455E, 0x81}, + {0x455F, 0x81}, + {0x4560, 0x86}, + {0x4561, 0x85}, + {0x4562, 0x85}, + {0x4563, 0x85}, + {0x4564, 0x8F}, + {0x4565, 0x8D}, + {0x4566, 0x8D}, + {0x4567, 0x8D}, + {0x4568, 0x99}, + {0x4569, 0x9A}, + {0x456A, 0x97}, + {0x456B, 0x99}, + {0x456C, 0x90}, + {0x456D, 0x95}, + {0x456E, 0x93}, + {0x456F, 0x92}, + {0x4570, 0x87}, + {0x4571, 0x8A}, + {0x4572, 0x88}, + {0x4573, 0x87}, + {0x4574, 0x81}, + {0x4575, 0x83}, + {0x4576, 0x82}, + {0x4577, 0x82}, + {0x4578, 0x7F}, + {0x4579, 0x80}, + {0x457A, 0x80}, + {0x457B, 0x80}, + {0x457C, 0x80}, + {0x457D, 0x80}, + {0x457E, 0x80}, + {0x457F, 0x80}, + {0x4580, 0x81}, + {0x4581, 0x81}, + {0x4582, 0x81}, + {0x4583, 0x81}, + {0x4584, 0x85}, + {0x4585, 0x85}, + {0x4586, 0x84}, + {0x4587, 0x85}, + {0x4588, 0x8E}, + {0x4589, 0x8D}, + {0x458A, 0x8C}, + {0x458B, 0x8D}, + {0x458C, 0x9B}, + {0x458D, 0x9B}, + {0x458E, 0x9A}, + {0x458F, 0x98}, + {0x4590, 0x94}, + {0x4591, 0x9A}, + {0x4592, 0x94}, + {0x4593, 0x90}, + {0x4594, 0x8A}, + {0x4595, 0x8D}, + {0x4596, 0x8C}, + {0x4597, 0x89}, + {0x4598, 0x84}, + {0x4599, 0x86}, + {0x459A, 0x85}, + {0x459B, 0x83}, + {0x459C, 0x82}, + {0x459D, 0x83}, + {0x459E, 0x82}, + {0x459F, 0x80}, + {0x45A0, 0x81}, + {0x45A1, 0x82}, + {0x45A2, 0x81}, + {0x45A3, 0x80}, + {0x45A4, 0x83}, + {0x45A5, 0x83}, + {0x45A6, 0x83}, + {0x45A7, 0x83}, + {0x45A8, 0x88}, + {0x45A9, 0x87}, + {0x45AA, 0x87}, + {0x45AB, 0x88}, + {0x45AC, 0x91}, + {0x45AD, 0x90}, + {0x45AE, 0x90}, + {0x45AF, 0x91}, + {0x45B0, 0x9F}, + {0x45B1, 0x9F}, + {0x45B2, 0x9E}, + {0x45B3, 0x9F}, + {0x45B4, 0x9F}, + {0x45B5, 0xA8}, + {0x45B6, 0xA6}, + {0x45B7, 0xA7}, + {0x45B8, 0x8D}, + {0x45B9, 0x95}, + {0x45BA, 0x90}, + {0x45BB, 0x8A}, + {0x45BC, 0x89}, + {0x45BD, 0x8D}, + {0x45BE, 0x88}, + {0x45BF, 0x86}, + {0x45C0, 0x84}, + {0x45C1, 0x86}, + {0x45C2, 0x85}, + {0x45C3, 0x82}, + {0x45C4, 0x84}, + {0x45C5, 0x85}, + {0x45C6, 0x85}, + {0x45C7, 0x83}, + {0x45C8, 0x86}, + {0x45C9, 0x86}, + {0x45CA, 0x86}, + {0x45CB, 0x85}, + {0x45CC, 0x8E}, + {0x45CD, 0x8D}, + {0x45CE, 0x8D}, + {0x45CF, 0x8C}, + {0x45D0, 0x99}, + {0x45D1, 0x98}, + {0x45D2, 0x98}, + {0x45D3, 0x98}, + {0x45D4, 0xA6}, + {0x45D5, 0xA9}, + {0x45D6, 0xA7}, + {0x45D7, 0xAC}, + + {0x0000, 0x01}, + + + {IMX390_TABLE_END, 0x00}, +}; + +enum { + IMX390_MODE_1920X1080_CROP_30FPS, + IMX390_MODE_START_STREAM, + IMX390_MODE_STOP_STREAM, +}; + +static imx390_reg *mode_table[] = { + [IMX390_MODE_1920X1080_CROP_30FPS] + = imx390_1920x1080_crop_30fps, + [IMX390_MODE_START_STREAM] + = imx390_start, + [IMX390_MODE_STOP_STREAM] + = imx390_stop, +}; + +static const int imx390_30fps[] = { + 30, +}; + +static const int imx390_60fps[] = { + 60, +}; + +static const int imx390_120fps[] = { + 120, +}; + +static const struct camera_common_frmfmt imx390_frmfmt[] = { + {{1920, 1080}, imx390_30fps, 1, 0, IMX390_MODE_1920X1080_CROP_30FPS}, +}; +#endif /* __IMX390_I2C_TABLES__ */ diff --git a/drivers/media/i2c/max9295.c b/drivers/media/i2c/max9295.c new file mode 100644 index 00000000..ac9f4c1b --- /dev/null +++ b/drivers/media/i2c/max9295.c @@ -0,0 +1,556 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +/* + * max9295.c - max9295 GMSL Serializer driver + */ + +#include +#include +#include + +/* register specifics */ +#define MAX9295_MIPI_RX0_ADDR 0x330 +#define MAX9295_MIPI_RX1_ADDR 0x331 +#define MAX9295_MIPI_RX2_ADDR 0x332 +#define MAX9295_MIPI_RX3_ADDR 0x333 + +#define MAX9295_PIPE_X_DT_ADDR 0x314 +#define MAX9295_PIPE_Y_DT_ADDR 0x316 +#define MAX9295_PIPE_Z_DT_ADDR 0x318 +#define MAX9295_PIPE_U_DT_ADDR 0x31A + +#define MAX9295_CTRL0_ADDR 0x10 +#define MAX9295_SRC_CTRL_ADDR 0x2BF +#define MAX9295_SRC_PWDN_ADDR 0x02BE +#define MAX9295_SRC_OUT_RCLK_ADDR 0x3F1 +#define MAX9295_START_PIPE_ADDR 0x311 +#define MAX9295_PIPE_EN_ADDR 0x2 +#define MAX9295_CSI_PORT_SEL_ADDR 0x308 + +#define MAX9295_I2C4_ADDR 0x44 +#define MAX9295_I2C5_ADDR 0x45 + +#define MAX9295_DEV_ADDR 0x00 + +#define MAX9295_STREAM_PIPE_UNUSED 0x22 +#define MAX9295_CSI_MODE_1X4 0x00 +#define MAX9295_CSI_MODE_2X2 0x03 +#define MAX9295_CSI_MODE_2X4 0x06 + +#define MAX9295_CSI_PORT_B(num_lanes) (((num_lanes) << 4) & 0xF0) +#define MAX9295_CSI_PORT_A(num_lanes) ((num_lanes) & 0x0F) + +#define MAX9295_CSI_1X4_MODE_LANE_MAP1 0xE0 +#define MAX9295_CSI_1X4_MODE_LANE_MAP2 0x04 + +#define MAX9295_CSI_2X4_MODE_LANE_MAP1 0xEE +#define MAX9295_CSI_2X4_MODE_LANE_MAP2 0xE4 + +#define MAX9295_CSI_2X2_MODE_LANE_MAP1 MAX9295_CSI_2X4_MODE_LANE_MAP1 +#define MAX9295_CSI_2X2_MODE_LANE_MAP2 MAX9295_CSI_2X4_MODE_LANE_MAP2 + +#define MAX9295_ST_ID_0 0x0 +#define MAX9295_ST_ID_1 0x1 +#define MAX9295_ST_ID_2 0x2 +#define MAX9295_ST_ID_3 0x3 + +#define MAX9295_PIPE_X_START_B 0x80 +#define MAX9295_PIPE_Y_START_B 0x40 +#define MAX9295_PIPE_Z_START_B 0x20 +#define MAX9295_PIPE_U_START_B 0x10 + +#define MAX9295_PIPE_X_START_A 0x1 +#define MAX9295_PIPE_Y_START_A 0x2 +#define MAX9295_PIPE_Z_START_A 0x4 +#define MAX9295_PIPE_U_START_A 0x8 + +#define MAX9295_START_PORT_A 0x10 +#define MAX9295_START_PORT_B 0x20 + +#define MAX9295_CSI_LN2 0x1 +#define MAX9295_CSI_LN4 0x3 + +#define MAX9295_EN_LINE_INFO 0x40 + +#define MAX9295_VID_TX_EN_X 0x10 +#define MAX9295_VID_TX_EN_Y 0x20 +#define MAX9295_VID_TX_EN_Z 0x40 +#define MAX9295_VID_TX_EN_U 0x80 + +#define MAX9295_VID_INIT 0x3 +#define MAX9295_SRC_RCLK 0x89 + +#define MAX9295_RESET_ALL 0x80 +#define MAX9295_RESET_SRC 0x60 +#define MAX9295_PWDN_GPIO 0x90 + +#define MAX9295_MAX_PIPES 0x4 + +struct max9295_client_ctx { + struct gmsl_link_ctx *g_ctx; + bool st_done; +}; + +struct max9295 { + struct i2c_client *i2c_client; + struct regmap *regmap; + struct max9295_client_ctx g_client; + struct mutex lock; + /* primary serializer properties */ + __u32 def_addr; + __u32 pst2_ref; +}; + +static struct max9295 *prim_priv__; + +struct map_ctx { + u8 dt; + u16 addr; + u8 val; + u8 st_id; +}; + +static int max9295_write_reg(struct device *dev, u16 addr, u8 val) +{ + struct max9295 *priv = dev_get_drvdata(dev); + int err; + + err = regmap_write(priv->regmap, addr, val); + if (err) + dev_err(dev, "%s:i2c write failed, 0x%x = %x\n", + __func__, addr, val); + + /* delay before next i2c command as required for SERDES link */ + usleep_range(100, 110); + + return err; +} + +int max9295_setup_streaming(struct device *dev) +{ + struct max9295 *priv = dev_get_drvdata(dev); + int err = 0; + u32 csi_mode; + u32 lane_map1; + u32 lane_map2; + u32 port; + u32 rx1_lanes; + u32 st_pipe; + u32 pipe_en; + u32 port_sel = 0; + struct gmsl_link_ctx *g_ctx; + u32 i; + u32 j; + u32 st_en; + + struct map_ctx map_pipe_dtype[] = { + {GMSL_CSI_DT_RAW_12, MAX9295_PIPE_Z_DT_ADDR, 0x2C, + MAX9295_ST_ID_2}, + {GMSL_CSI_DT_UED_U1, MAX9295_PIPE_X_DT_ADDR, 0x30, + MAX9295_ST_ID_0}, + {GMSL_CSI_DT_EMBED, MAX9295_PIPE_Y_DT_ADDR, 0x12, + MAX9295_ST_ID_1}, + }; + + mutex_lock(&priv->lock); + + if (!priv->g_client.g_ctx) { + dev_err(dev, "%s: no sdev client found\n", __func__); + err = -EINVAL; + goto error; + } + + if (priv->g_client.st_done) { + dev_dbg(dev, "%s: stream setup is already done\n", __func__); + goto error; + } + + g_ctx = priv->g_client.g_ctx; + + switch (g_ctx->csi_mode) { + case GMSL_CSI_1X4_MODE: + csi_mode = MAX9295_CSI_MODE_1X4; + lane_map1 = MAX9295_CSI_1X4_MODE_LANE_MAP1; + lane_map2 = MAX9295_CSI_1X4_MODE_LANE_MAP2; + rx1_lanes = MAX9295_CSI_LN4; + break; + case GMSL_CSI_2X2_MODE: + csi_mode = MAX9295_CSI_MODE_2X2; + lane_map1 = MAX9295_CSI_2X2_MODE_LANE_MAP1; + lane_map2 = MAX9295_CSI_2X2_MODE_LANE_MAP2; + rx1_lanes = MAX9295_CSI_LN2; + break; + case GMSL_CSI_2X4_MODE: + csi_mode = MAX9295_CSI_MODE_2X4; + lane_map1 = MAX9295_CSI_2X4_MODE_LANE_MAP1; + lane_map2 = MAX9295_CSI_2X4_MODE_LANE_MAP2; + rx1_lanes = MAX9295_CSI_LN4; + break; + default: + dev_err(dev, "%s: invalid csi mode\n", __func__); + err = -EINVAL; + goto error; + } + + port = (g_ctx->src_csi_port == GMSL_CSI_PORT_B) ? + MAX9295_CSI_PORT_B(rx1_lanes) : + MAX9295_CSI_PORT_A(rx1_lanes); + + max9295_write_reg(dev, MAX9295_MIPI_RX0_ADDR, csi_mode); + max9295_write_reg(dev, MAX9295_MIPI_RX1_ADDR, port); + max9295_write_reg(dev, MAX9295_MIPI_RX2_ADDR, lane_map1); + max9295_write_reg(dev, MAX9295_MIPI_RX3_ADDR, lane_map2); + + for (i = 0; i < g_ctx->num_streams; i++) { + struct gmsl_stream *g_stream = &g_ctx->streams[i]; + + g_stream->st_id_sel = GMSL_ST_ID_UNUSED; + for (j = 0; j < ARRAY_SIZE(map_pipe_dtype); j++) { + if (map_pipe_dtype[j].dt == g_stream->st_data_type) { + /* + * TODO: + * 1) Remove link specific overrides, depends + * on #2. + * 2) Add support for vc id based stream sel + * overrides TX_SRC_SEL. would be useful in + * using same mappings in all ser devs. + */ + if (g_ctx->serdes_csi_link == + GMSL_SERDES_CSI_LINK_B) { + map_pipe_dtype[j].addr += 2; + map_pipe_dtype[j].st_id += 1; + } + + g_stream->st_id_sel = map_pipe_dtype[j].st_id; + st_en = (map_pipe_dtype[j].addr == + MAX9295_PIPE_X_DT_ADDR) ? + 0xC0 : 0x40; + + max9295_write_reg(dev, map_pipe_dtype[j].addr, + (st_en | map_pipe_dtype[j].val)); + } + } + } + + for (i = 0; i < g_ctx->num_streams; i++) + if (g_ctx->streams[i].st_id_sel != GMSL_ST_ID_UNUSED) + port_sel |= (1 << g_ctx->streams[i].st_id_sel); + + if (g_ctx->src_csi_port == GMSL_CSI_PORT_B) { + st_pipe = (MAX9295_PIPE_X_START_B | MAX9295_PIPE_Y_START_B | + MAX9295_PIPE_Z_START_B | MAX9295_PIPE_U_START_B); + port_sel |= (MAX9295_EN_LINE_INFO | MAX9295_START_PORT_B); + } else { + st_pipe = MAX9295_PIPE_X_START_A | MAX9295_PIPE_Y_START_A | + MAX9295_PIPE_Z_START_A | MAX9295_PIPE_U_START_A; + port_sel |= (MAX9295_EN_LINE_INFO | MAX9295_START_PORT_A); + } + + pipe_en = (MAX9295_VID_TX_EN_X | MAX9295_VID_TX_EN_Y | + MAX9295_VID_TX_EN_Z | MAX9295_VID_TX_EN_U | MAX9295_VID_INIT); + + max9295_write_reg(dev, MAX9295_START_PIPE_ADDR, st_pipe); + max9295_write_reg(dev, MAX9295_CSI_PORT_SEL_ADDR, port_sel); + max9295_write_reg(dev, MAX9295_PIPE_EN_ADDR, pipe_en); + + priv->g_client.st_done = true; + +error: + mutex_unlock(&priv->lock); + return err; +} +EXPORT_SYMBOL(max9295_setup_streaming); + +int max9295_setup_control(struct device *dev) +{ + struct max9295 *priv = dev_get_drvdata(dev); + int err = 0; + struct gmsl_link_ctx *g_ctx; + u32 offset1 = 0; + u32 offset2 = 0; + u32 i; + + u8 i2c_ovrd[] = { + 0x6B, 0x10, + 0x73, 0x11, + 0x7B, 0x30, + 0x83, 0x30, + 0x93, 0x30, + 0x9B, 0x30, + 0xA3, 0x30, + 0xAB, 0x30, + 0x8B, 0x30, + }; + + u8 addr_offset[] = { + 0x80, 0x00, 0x00, + 0x84, 0x00, 0x01, + 0xC0, 0x02, 0x02, + 0xC4, 0x02, 0x03, + }; + + mutex_lock(&priv->lock); + + if (!priv->g_client.g_ctx) { + dev_err(dev, "%s: no sensor dev client found\n", __func__); + err = -EINVAL; + goto error; + } + + g_ctx = priv->g_client.g_ctx; + + if (prim_priv__) { + /* update address reassingment */ + max9295_write_reg(&prim_priv__->i2c_client->dev, + MAX9295_DEV_ADDR, (g_ctx->ser_reg << 1)); + } + + if (g_ctx->serdes_csi_link == GMSL_SERDES_CSI_LINK_A) + err = max9295_write_reg(dev, MAX9295_CTRL0_ADDR, 0x21); + else + err = max9295_write_reg(dev, MAX9295_CTRL0_ADDR, 0x22); + + /* check if serializer device exists */ + if (err) { + dev_err(dev, "%s: ERROR: ser device not found\n", __func__); + goto error; + } + + /* delay to settle link */ + msleep(100); + + for (i = 0; i < ARRAY_SIZE(addr_offset); i += 3) { + if ((g_ctx->ser_reg << 1) == addr_offset[i]) { + offset1 = addr_offset[i+1]; + offset2 = addr_offset[i+2]; + break; + } + } + + if (i == ARRAY_SIZE(addr_offset)) { + dev_err(dev, "%s: invalid ser slave address\n", __func__); + err = -EINVAL; + goto error; + } + + for (i = 0; i < ARRAY_SIZE(i2c_ovrd); i += 2) { + /* update address overrides */ + i2c_ovrd[i+1] += (i < 4) ? offset1 : offset2; + + /* i2c passthrough2 must be configured once for all devices */ + if ((i2c_ovrd[i] == 0x8B) && prim_priv__ && + prim_priv__->pst2_ref) + continue; + + max9295_write_reg(dev, i2c_ovrd[i], i2c_ovrd[i+1]); + } + + /* dev addr pass-through2 ref */ + if (prim_priv__) + prim_priv__->pst2_ref++; + + max9295_write_reg(dev, MAX9295_I2C4_ADDR, (g_ctx->sdev_reg << 1)); + max9295_write_reg(dev, MAX9295_I2C5_ADDR, (g_ctx->sdev_def << 1)); + + max9295_write_reg(dev, MAX9295_SRC_PWDN_ADDR, MAX9295_PWDN_GPIO); + max9295_write_reg(dev, MAX9295_SRC_CTRL_ADDR, MAX9295_RESET_SRC); + max9295_write_reg(dev, MAX9295_SRC_OUT_RCLK_ADDR, MAX9295_SRC_RCLK); + + g_ctx->serdev_found = true; + +error: + mutex_unlock(&priv->lock); + return err; +} +EXPORT_SYMBOL(max9295_setup_control); + +int max9295_reset_control(struct device *dev) +{ + struct max9295 *priv = dev_get_drvdata(dev); + int err = 0; + + mutex_lock(&priv->lock); + if (!priv->g_client.g_ctx) { + dev_err(dev, "%s: no sdev client found\n", __func__); + err = -EINVAL; + goto error; + } + + priv->g_client.st_done = false; + + if (prim_priv__) { + prim_priv__->pst2_ref--; + + max9295_write_reg(dev, MAX9295_DEV_ADDR, + (prim_priv__->def_addr << 1)); + + max9295_write_reg(&prim_priv__->i2c_client->dev, + MAX9295_CTRL0_ADDR, MAX9295_RESET_ALL); + } + +error: + mutex_unlock(&priv->lock); + return err; +} +EXPORT_SYMBOL(max9295_reset_control); + +int max9295_sdev_pair(struct device *dev, struct gmsl_link_ctx *g_ctx) +{ + struct max9295 *priv; + int err = 0; + + if (!dev || !g_ctx || !g_ctx->s_dev) { + dev_err(dev, "%s: invalid input params\n", __func__); + return -EINVAL; + } + + priv = dev_get_drvdata(dev); + mutex_lock(&priv->lock); + if (priv->g_client.g_ctx) { + dev_err(dev, "%s: device already paired\n", __func__); + err = -EINVAL; + goto error; + } + + priv->g_client.st_done = false; + + priv->g_client.g_ctx = g_ctx; + +error: + mutex_unlock(&priv->lock); + return 0; +} +EXPORT_SYMBOL(max9295_sdev_pair); + +int max9295_sdev_unpair(struct device *dev, struct device *s_dev) +{ + struct max9295 *priv = NULL; + int err = 0; + + if (!dev || !s_dev) { + dev_err(dev, "%s: invalid input params\n", __func__); + return -EINVAL; + } + + priv = dev_get_drvdata(dev); + + mutex_lock(&priv->lock); + + if (!priv->g_client.g_ctx) { + dev_err(dev, "%s: device is not paired\n", __func__); + err = -ENOMEM; + goto error; + } + + if (priv->g_client.g_ctx->s_dev != s_dev) { + dev_err(dev, "%s: invalid device\n", __func__); + err = -EINVAL; + goto error; + } + + priv->g_client.g_ctx = NULL; + priv->g_client.st_done = false; + +error: + mutex_unlock(&priv->lock); + return err; +} +EXPORT_SYMBOL(max9295_sdev_unpair); + +static struct regmap_config max9295_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, +}; + +static int max9295_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct max9295 *priv; + int err = 0; + struct device_node *node = client->dev.of_node; + + dev_info(&client->dev, "[MAX9295]: probing GMSL Serializer\n"); + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + priv->i2c_client = client; + priv->regmap = devm_regmap_init_i2c(priv->i2c_client, + &max9295_regmap_config); + if (IS_ERR(priv->regmap)) { + dev_err(&client->dev, + "regmap init failed: %ld\n", PTR_ERR(priv->regmap)); + return -ENODEV; + } + + mutex_init(&priv->lock); + + if (of_get_property(node, "is-prim-ser", NULL)) { + if (prim_priv__) { + dev_err(&client->dev, + "prim-ser already exists\n"); + return -EEXIST; + } + + err = of_property_read_u32(node, "reg", &priv->def_addr); + if (err < 0) { + dev_err(&client->dev, "reg not found\n"); + return -EINVAL; + } + + prim_priv__ = priv; + } + + dev_set_drvdata(&client->dev, priv); + + /* dev communication gets validated when GMSL link setup is done */ + dev_info(&client->dev, "%s: success\n", __func__); + + return err; +} + +#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE) +static int max9295_remove(struct i2c_client *client) +#else +static void max9295_remove(struct i2c_client *client) +#endif +{ + struct max9295 *priv; + + if (client != NULL) { + priv = dev_get_drvdata(&client->dev); + mutex_destroy(&priv->lock); + i2c_unregister_device(client); + client = NULL; + } +#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE) + return 0; +#endif +} + +static const struct i2c_device_id max9295_id[] = { + { "max9295", 0 }, + { }, +}; + +static const struct of_device_id max9295_of_match[] = { + { .compatible = "maxim,max9295", }, + { }, +}; +MODULE_DEVICE_TABLE(of, max9295_of_match); +MODULE_DEVICE_TABLE(i2c, max9295_id); + +static struct i2c_driver max9295_i2c_driver = { + .driver = { + .name = "max9295", + .owner = THIS_MODULE, + }, + .probe = max9295_probe, + .remove = max9295_remove, + .id_table = max9295_id, +}; + +module_i2c_driver(max9295_i2c_driver); + +MODULE_DESCRIPTION("GMSL Serializer driver max9295"); +MODULE_AUTHOR("Sudhir Vyas "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/max9296.c b/drivers/media/i2c/max9296.c new file mode 100644 index 00000000..50168742 --- /dev/null +++ b/drivers/media/i2c/max9296.c @@ -0,0 +1,932 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +/* + * max9296.c - max9296 GMSL Deserializer driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* register specifics */ +#define MAX9296_DST_CSI_MODE_ADDR 0x330 +#define MAX9296_LANE_MAP1_ADDR 0x333 +#define MAX9296_LANE_MAP2_ADDR 0x334 + +#define MAX9296_LANE_CTRL0_ADDR 0x40A +#define MAX9296_LANE_CTRL1_ADDR 0x44A +#define MAX9296_LANE_CTRL2_ADDR 0x48A +#define MAX9296_LANE_CTRL3_ADDR 0x4CA + +#define MAX9296_TX11_PIPE_X_EN_ADDR 0x40B +#define MAX9296_TX45_PIPE_X_DST_CTRL_ADDR 0x42D + +#define MAX9296_PIPE_X_SRC_0_MAP_ADDR 0x40D +#define MAX9296_PIPE_X_DST_0_MAP_ADDR 0x40E +#define MAX9296_PIPE_X_SRC_1_MAP_ADDR 0x40F +#define MAX9296_PIPE_X_DST_1_MAP_ADDR 0x410 +#define MAX9296_PIPE_X_SRC_2_MAP_ADDR 0x411 +#define MAX9296_PIPE_X_DST_2_MAP_ADDR 0x412 + +#define MAX9296_PIPE_X_ST_SEL_ADDR 0x50 + +#define MAX9296_PWDN_PHYS_ADDR 0x332 +#define MAX9296_PHY1_CLK_ADDR 0x320 +#define MAX9296_CTRL0_ADDR 0x10 + +/* data defines */ +#define MAX9296_CSI_MODE_4X2 0x1 +#define MAX9296_CSI_MODE_2X4 0x4 +#define MAX9296_LANE_MAP1_4X2 0x44 +#define MAX9296_LANE_MAP2_4X2 0x44 +#define MAX9296_LANE_MAP1_2X4 0x4E +#define MAX9296_LANE_MAP2_2X4 0xE4 + +#define MAX9296_LANE_CTRL_MAP(num_lanes) \ + (((num_lanes) << 6) & 0xF0) + +#define MAX9296_ALLPHYS_NOSTDBY 0xF0 +#define MAX9296_ST_ID_SEL_INVALID 0xF + +#define MAX9296_PHY1_CLK 0x2C + +#define MAX9296_RESET_ALL 0x80 + +/* Dual GMSL MAX9296A/B */ +#define MAX9296_MAX_SOURCES 2 + +#define MAX9296_MAX_PIPES 4 + +#define MAX9296_PIPE_X 0 +#define MAX9296_PIPE_Y 1 +#define MAX9296_PIPE_Z 2 +#define MAX9296_PIPE_U 3 +#define MAX9296_PIPE_INVALID 0xF + + +#define MAX9296_CSI_CTRL_0 0 +#define MAX9296_CSI_CTRL_1 1 +#define MAX9296_CSI_CTRL_2 2 +#define MAX9296_CSI_CTRL_3 3 + +#define MAX9296_INVAL_ST_ID 0xFF + +/* Use reset value as per spec, confirm with vendor */ +#define MAX9296_RESET_ST_ID 0x00 + +struct max9296_source_ctx { + struct gmsl_link_ctx *g_ctx; + bool st_enabled; +}; + +struct pipe_ctx { + u32 id; + u32 dt_type; + u32 dst_csi_ctrl; + u32 st_count; + u32 st_id_sel; +}; + +struct max9296 { + struct i2c_client *i2c_client; + struct regmap *regmap; + u32 num_src; + u32 max_src; + u32 num_src_found; + u32 src_link; + bool splitter_enabled; + struct max9296_source_ctx sources[MAX9296_MAX_SOURCES]; + struct mutex lock; + u32 sdev_ref; + bool lane_setup; + bool link_setup; + struct pipe_ctx pipe[MAX9296_MAX_PIPES]; + u8 csi_mode; + u8 lane_mp1; + u8 lane_mp2; + int reset_gpio; + int pw_ref; + struct regulator *vdd_cam_1v2; +}; + +static int max9296_write_reg(struct device *dev, + u16 addr, u8 val) +{ + struct max9296 *priv; + int err; + + priv = dev_get_drvdata(dev); + + err = regmap_write(priv->regmap, addr, val); + if (err) + dev_err(dev, + "%s:i2c write failed, 0x%x = %x\n", + __func__, addr, val); + + /* delay before next i2c command as required for SERDES link */ + usleep_range(100, 110); + + return err; +} + +static int max9296_get_sdev_idx(struct device *dev, + struct device *s_dev, unsigned int *idx) +{ + struct max9296 *priv = dev_get_drvdata(dev); + unsigned int i; + int err = 0; + + mutex_lock(&priv->lock); + for (i = 0; i < priv->max_src; i++) { + if (priv->sources[i].g_ctx->s_dev == s_dev) + break; + } + if (i == priv->max_src) { + dev_err(dev, "no sdev found\n"); + err = -EINVAL; + goto ret; + } + + if (idx) + *idx = i; + +ret: + mutex_unlock(&priv->lock); + return err; +} + +static void max9296_pipes_reset(struct max9296 *priv) +{ + /* + * This is default pipes combination. add more mappings + * for other combinations and requirements. + */ + struct pipe_ctx pipe_defaults[] = { + {MAX9296_PIPE_X, GMSL_CSI_DT_RAW_12, + MAX9296_CSI_CTRL_1, 0, MAX9296_INVAL_ST_ID}, + {MAX9296_PIPE_Y, GMSL_CSI_DT_RAW_12, + MAX9296_CSI_CTRL_1, 0, MAX9296_INVAL_ST_ID}, + {MAX9296_PIPE_Z, GMSL_CSI_DT_EMBED, + MAX9296_CSI_CTRL_1, 0, MAX9296_INVAL_ST_ID}, + {MAX9296_PIPE_U, GMSL_CSI_DT_EMBED, + MAX9296_CSI_CTRL_1, 0, MAX9296_INVAL_ST_ID} + }; + + /* + * Add DT props for num-streams and stream sequence, and based on that + * set the appropriate pipes defaults. + * For now default it supports "2 RAW12 and 2 EMBED" 1:1 mappings. + */ + memcpy(priv->pipe, pipe_defaults, sizeof(pipe_defaults)); +} + +static void max9296_reset_ctx(struct max9296 *priv) +{ + unsigned int i; + + priv->link_setup = false; + priv->lane_setup = false; + priv->num_src_found = 0; + priv->src_link = 0; + priv->splitter_enabled = false; + max9296_pipes_reset(priv); + for (i = 0; i < priv->num_src; i++) + priv->sources[i].st_enabled = false; +} + +int max9296_power_on(struct device *dev) +{ + struct max9296 *priv = dev_get_drvdata(dev); + int err = 0; + + mutex_lock(&priv->lock); + if (priv->pw_ref == 0) { + usleep_range(1, 2); + if (priv->reset_gpio) + gpio_set_value(priv->reset_gpio, 0); + + usleep_range(30, 50); + + if (priv->vdd_cam_1v2) { + err = regulator_enable(priv->vdd_cam_1v2); + if (unlikely(err)) + goto ret; + } + + usleep_range(30, 50); + + /*exit reset mode: XCLR */ + if (priv->reset_gpio) { + gpio_set_value(priv->reset_gpio, 0); + usleep_range(30, 50); + gpio_set_value(priv->reset_gpio, 1); + usleep_range(30, 50); + } + + /* delay to settle reset */ + msleep(20); + } + + priv->pw_ref++; + +ret: + mutex_unlock(&priv->lock); + + return err; +} +EXPORT_SYMBOL(max9296_power_on); + +void max9296_power_off(struct device *dev) +{ + struct max9296 *priv = dev_get_drvdata(dev); + + mutex_lock(&priv->lock); + priv->pw_ref--; + + if (priv->pw_ref == 0) { + /* enter reset mode: XCLR */ + usleep_range(1, 2); + if (priv->reset_gpio) + gpio_set_value(priv->reset_gpio, 0); + + if (priv->vdd_cam_1v2) + regulator_disable(priv->vdd_cam_1v2); + } + + mutex_unlock(&priv->lock); +} +EXPORT_SYMBOL(max9296_power_off); + +static int max9296_write_link(struct device *dev, u32 link) +{ + if (link == GMSL_SERDES_CSI_LINK_A) { + max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x01); + max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x21); + } else if (link == GMSL_SERDES_CSI_LINK_B) { + max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x02); + max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x22); + } else { + dev_err(dev, "%s: invalid gmsl link\n", __func__); + return -EINVAL; + } + + /* delay to settle link */ + msleep(100); + + return 0; +} + +int max9296_setup_link(struct device *dev, struct device *s_dev) +{ + struct max9296 *priv = dev_get_drvdata(dev); + int err = 0; + unsigned int i = 0; + + err = max9296_get_sdev_idx(dev, s_dev, &i); + if (err) + return err; + + mutex_lock(&priv->lock); + + if (!priv->splitter_enabled) { + err = max9296_write_link(dev, + priv->sources[i].g_ctx->serdes_csi_link); + if (err) + goto ret; + + priv->link_setup = true; + } + +ret: + mutex_unlock(&priv->lock); + + return err; +} +EXPORT_SYMBOL(max9296_setup_link); + +int max9296_setup_control(struct device *dev, struct device *s_dev) +{ + struct max9296 *priv = dev_get_drvdata(dev); + int err = 0; + unsigned int i = 0; + + err = max9296_get_sdev_idx(dev, s_dev, &i); + if (err) + return err; + + mutex_lock(&priv->lock); + + if (!priv->link_setup) { + dev_err(dev, "%s: invalid state\n", __func__); + err = -EINVAL; + goto error; + } + + if (priv->sources[i].g_ctx->serdev_found) { + priv->num_src_found++; + priv->src_link = priv->sources[i].g_ctx->serdes_csi_link; + } + + /* Enable splitter mode */ + if ((priv->max_src > 1U) && + (priv->num_src_found > 0U) && + (priv->splitter_enabled == false)) { + max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x03); + max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x23); + + priv->splitter_enabled = true; + + /* delay to settle link */ + msleep(100); + } + + max9296_write_reg(dev, + MAX9296_PWDN_PHYS_ADDR, MAX9296_ALLPHYS_NOSTDBY); + + priv->sdev_ref++; + + /* Reset splitter mode if all devices are not found */ + if ((priv->sdev_ref == priv->max_src) && + (priv->splitter_enabled == true) && + (priv->num_src_found > 0U) && + (priv->num_src_found < priv->max_src)) { + err = max9296_write_link(dev, priv->src_link); + if (err) + goto error; + + priv->splitter_enabled = false; + } + +error: + mutex_unlock(&priv->lock); + return err; +} +EXPORT_SYMBOL(max9296_setup_control); + +int max9296_reset_control(struct device *dev, struct device *s_dev) +{ + struct max9296 *priv = dev_get_drvdata(dev); + + mutex_lock(&priv->lock); + if (!priv->sdev_ref) { + dev_info(dev, "%s: dev is already in reset state\n", __func__); + goto ret; + } + + priv->sdev_ref--; + if (priv->sdev_ref == 0) { + max9296_reset_ctx(priv); + max9296_write_reg(dev, MAX9296_CTRL0_ADDR, MAX9296_RESET_ALL); + + /* delay to settle reset */ + msleep(100); + } + +ret: + mutex_unlock(&priv->lock); + + return 0; +} +EXPORT_SYMBOL(max9296_reset_control); + +int max9296_sdev_register(struct device *dev, struct gmsl_link_ctx *g_ctx) +{ + struct max9296 *priv = NULL; + unsigned int i; + int err = 0; + + if (!dev || !g_ctx || !g_ctx->s_dev) { + dev_err(dev, "%s: invalid input params\n", __func__); + return -EINVAL; + } + + priv = dev_get_drvdata(dev); + + mutex_lock(&priv->lock); + + if (priv->num_src > priv->max_src) { + dev_err(dev, + "%s: MAX9296 inputs size exhausted\n", __func__); + err = -ENOMEM; + goto error; + } + + /* Check csi mode compatibility */ + if (!((priv->csi_mode == MAX9296_CSI_MODE_2X4) ? + ((g_ctx->csi_mode == GMSL_CSI_1X4_MODE) || + (g_ctx->csi_mode == GMSL_CSI_2X4_MODE)) : + ((g_ctx->csi_mode == GMSL_CSI_2X2_MODE) || + (g_ctx->csi_mode == GMSL_CSI_4X2_MODE)))) { + dev_err(dev, + "%s: csi mode not supported\n", __func__); + err = -EINVAL; + goto error; + } + + for (i = 0; i < priv->num_src; i++) { + if (g_ctx->serdes_csi_link == + priv->sources[i].g_ctx->serdes_csi_link) { + dev_err(dev, + "%s: serdes csi link is in use\n", __func__); + err = -EINVAL; + goto error; + } + /* + * All sdevs should have same num-csi-lanes regardless of + * dst csi port selected. + * Later if there is any usecase which requires each port + * to be configured with different num-csi-lanes, then this + * check should be performed per port. + */ + if (g_ctx->num_csi_lanes != + priv->sources[i].g_ctx->num_csi_lanes) { + dev_err(dev, + "%s: csi num lanes mismatch\n", __func__); + err = -EINVAL; + goto error; + } + } + + priv->sources[priv->num_src].g_ctx = g_ctx; + priv->sources[priv->num_src].st_enabled = false; + + priv->num_src++; + +error: + mutex_unlock(&priv->lock); + return err; +} +EXPORT_SYMBOL(max9296_sdev_register); + +int max9296_sdev_unregister(struct device *dev, struct device *s_dev) +{ + struct max9296 *priv = NULL; + int err = 0; + unsigned int i = 0; + + if (!dev || !s_dev) { + dev_err(dev, "%s: invalid input params\n", __func__); + return -EINVAL; + } + + priv = dev_get_drvdata(dev); + mutex_lock(&priv->lock); + + if (priv->num_src == 0) { + dev_err(dev, "%s: no source found\n", __func__); + err = -ENODATA; + goto error; + } + + for (i = 0; i < priv->num_src; i++) { + if (s_dev == priv->sources[i].g_ctx->s_dev) { + priv->sources[i].g_ctx = NULL; + break; + } + } + + if (i == priv->num_src) { + dev_err(dev, + "%s: requested device not found\n", __func__); + err = -EINVAL; + goto error; + } + priv->num_src--; + +error: + mutex_unlock(&priv->lock); + return err; +} +EXPORT_SYMBOL(max9296_sdev_unregister); + +static int max9296_get_available_pipe(struct device *dev, + u32 st_data_type, u32 dst_csi_port) +{ + struct max9296 *priv = dev_get_drvdata(dev); + int i; + + for (i = 0; i < MAX9296_MAX_PIPES; i++) { + /* + * TODO: Enable a pipe for multi stream configuration having + * similar stream data type. For now use st_count as a flag + * for 1 to 1 mapping in pipe and stream data type, same can + * be extended as count for many to 1 mapping. Would also need + * few more checks such as input stream id select, dst port etc. + */ + if ((priv->pipe[i].dt_type == st_data_type) && + ((dst_csi_port == GMSL_CSI_PORT_A) ? + (priv->pipe[i].dst_csi_ctrl == + MAX9296_CSI_CTRL_0) || + (priv->pipe[i].dst_csi_ctrl == + MAX9296_CSI_CTRL_1) : + (priv->pipe[i].dst_csi_ctrl == + MAX9296_CSI_CTRL_2) || + (priv->pipe[i].dst_csi_ctrl == + MAX9296_CSI_CTRL_3)) && + (!priv->pipe[i].st_count)) + break; + } + + if (i == MAX9296_MAX_PIPES) { + dev_err(dev, "%s: all pipes are busy\n", __func__); + return -ENOMEM; + } + + return i; +} + +struct reg_pair { + u16 addr; + u8 val; +}; + +static int max9296_setup_pipeline(struct device *dev, + struct gmsl_link_ctx *g_ctx) +{ + struct max9296 *priv = dev_get_drvdata(dev); + struct gmsl_stream *g_stream; + struct reg_pair *map_list; + u32 arr_sz = 0; + int pipe_id = 0; + u32 i = 0; + u32 j = 0; + u32 vc_idx = 0; + + for (i = 0; i < g_ctx->num_streams; i++) { + /* Base data type mapping: pipeX/RAW12/CSICNTR1 */ + struct reg_pair map_pipe_raw12[] = { + /* addr, val */ + {MAX9296_TX11_PIPE_X_EN_ADDR, 0x7}, + {MAX9296_TX45_PIPE_X_DST_CTRL_ADDR, 0x15}, + {MAX9296_PIPE_X_SRC_0_MAP_ADDR, 0x2C}, + {MAX9296_PIPE_X_DST_0_MAP_ADDR, 0x2C}, + {MAX9296_PIPE_X_SRC_1_MAP_ADDR, 0x00}, + {MAX9296_PIPE_X_DST_1_MAP_ADDR, 0x00}, + {MAX9296_PIPE_X_SRC_2_MAP_ADDR, 0x01}, + {MAX9296_PIPE_X_DST_2_MAP_ADDR, 0x01}, + }; + + /* Base data type mapping: pipeX/EMBED/CSICNTR1 */ + struct reg_pair map_pipe_embed[] = { + /* addr, val */ + {MAX9296_TX11_PIPE_X_EN_ADDR, 0x7}, + {MAX9296_TX45_PIPE_X_DST_CTRL_ADDR, 0x15}, + {MAX9296_PIPE_X_SRC_0_MAP_ADDR, 0x12}, + {MAX9296_PIPE_X_DST_0_MAP_ADDR, 0x12}, + {MAX9296_PIPE_X_SRC_1_MAP_ADDR, 0x00}, + {MAX9296_PIPE_X_DST_1_MAP_ADDR, 0x00}, + {MAX9296_PIPE_X_SRC_2_MAP_ADDR, 0x01}, + {MAX9296_PIPE_X_DST_2_MAP_ADDR, 0x01}, + }; + + g_stream = &g_ctx->streams[i]; + g_stream->des_pipe = MAX9296_PIPE_INVALID; + + if (g_stream->st_data_type == GMSL_CSI_DT_RAW_12) { + map_list = map_pipe_raw12; + arr_sz = ARRAY_SIZE(map_pipe_raw12); + } else if (g_stream->st_data_type == GMSL_CSI_DT_EMBED) { + map_list = map_pipe_embed; + arr_sz = ARRAY_SIZE(map_pipe_embed); + } else if (g_stream->st_data_type == GMSL_CSI_DT_UED_U1) { + dev_dbg(dev, + "%s: No mapping for GMSL_CSI_DT_UED_U1\n", + __func__); + continue; + } else { + dev_err(dev, "%s: Invalid data type\n", __func__); + return -EINVAL; + } + + pipe_id = max9296_get_available_pipe(dev, + g_stream->st_data_type, g_ctx->dst_csi_port); + if (pipe_id < 0) + return pipe_id; + + for (j = 0, vc_idx = 3; j < arr_sz; j++, vc_idx += 2) { + /* update pipe configuration */ + map_list[j].addr += (0x40 * pipe_id); + /* update vc id configuration */ + if (vc_idx < arr_sz) + map_list[vc_idx].val |= + (g_ctx->dst_vc << 6); + + max9296_write_reg(dev, map_list[j].addr, + map_list[j].val); + } + + /* Set stream id select input */ + if (g_stream->st_id_sel == GMSL_ST_ID_UNUSED) { + dev_err(dev, "%s: Invalid stream st_id_sel\n", + __func__); + return -EINVAL; + } + + g_stream->des_pipe = MAX9296_PIPE_X_ST_SEL_ADDR + pipe_id; + + /* Update pipe internals */ + priv->pipe[pipe_id].st_count++; + priv->pipe[pipe_id].st_id_sel = g_stream->st_id_sel; + } + + return 0; +} + +int max9296_start_streaming(struct device *dev, struct device *s_dev) +{ + struct max9296 *priv = dev_get_drvdata(dev); + struct gmsl_link_ctx *g_ctx; + struct gmsl_stream *g_stream; + int err = 0; + unsigned int i = 0; + + err = max9296_get_sdev_idx(dev, s_dev, &i); + if (err) + return err; + + mutex_lock(&priv->lock); + g_ctx = priv->sources[i].g_ctx; + + for (i = 0; i < g_ctx->num_streams; i++) { + g_stream = &g_ctx->streams[i]; + + if (g_stream->des_pipe != MAX9296_PIPE_INVALID) + max9296_write_reg(dev, g_stream->des_pipe, + g_stream->st_id_sel); + } + mutex_unlock(&priv->lock); + + return 0; +} +EXPORT_SYMBOL(max9296_start_streaming); + +int max9296_stop_streaming(struct device *dev, struct device *s_dev) +{ + struct max9296 *priv = dev_get_drvdata(dev); + struct gmsl_link_ctx *g_ctx; + struct gmsl_stream *g_stream; + int err = 0; + unsigned int i = 0; + + err = max9296_get_sdev_idx(dev, s_dev, &i); + if (err) + return err; + + mutex_lock(&priv->lock); + g_ctx = priv->sources[i].g_ctx; + + for (i = 0; i < g_ctx->num_streams; i++) { + g_stream = &g_ctx->streams[i]; + + if (g_stream->des_pipe != MAX9296_PIPE_INVALID) + max9296_write_reg(dev, g_stream->des_pipe, + MAX9296_RESET_ST_ID); + } + + mutex_unlock(&priv->lock); + + return 0; +} +EXPORT_SYMBOL(max9296_stop_streaming); + +int max9296_setup_streaming(struct device *dev, struct device *s_dev) +{ + struct max9296 *priv = dev_get_drvdata(dev); + struct gmsl_link_ctx *g_ctx; + int err = 0; + unsigned int i = 0; + u16 lane_ctrl_addr; + + err = max9296_get_sdev_idx(dev, s_dev, &i); + if (err) + return err; + + mutex_lock(&priv->lock); + if (priv->sources[i].st_enabled) + goto ret; + + g_ctx = priv->sources[i].g_ctx; + + err = max9296_setup_pipeline(dev, g_ctx); + if (err) + goto ret; + + /* Derive CSI lane map register */ + switch (g_ctx->dst_csi_port) { + case GMSL_CSI_PORT_A: + case GMSL_CSI_PORT_D: + lane_ctrl_addr = MAX9296_LANE_CTRL1_ADDR; + break; + case GMSL_CSI_PORT_B: + case GMSL_CSI_PORT_E: + lane_ctrl_addr = MAX9296_LANE_CTRL2_ADDR; + break; + case GMSL_CSI_PORT_C: + lane_ctrl_addr = MAX9296_LANE_CTRL0_ADDR; + break; + case GMSL_CSI_PORT_F: + lane_ctrl_addr = MAX9296_LANE_CTRL3_ADDR; + break; + default: + dev_err(dev, "%s: invalid gmsl csi port!\n", __func__); + err = -EINVAL; + goto ret; + }; + + /* + * rewrite num_lanes to same dst port should not be an issue, + * as the device compatibility is already + * checked during sdev registration against the des properties. + */ + max9296_write_reg(dev, lane_ctrl_addr, + MAX9296_LANE_CTRL_MAP(g_ctx->num_csi_lanes-1)); + + if (!priv->lane_setup) { + max9296_write_reg(dev, + MAX9296_DST_CSI_MODE_ADDR, priv->csi_mode); + max9296_write_reg(dev, + MAX9296_LANE_MAP1_ADDR, priv->lane_mp1); + max9296_write_reg(dev, + MAX9296_LANE_MAP2_ADDR, priv->lane_mp2); + max9296_write_reg(dev, + MAX9296_PHY1_CLK_ADDR, MAX9296_PHY1_CLK); + + priv->lane_setup = true; + } + + priv->sources[i].st_enabled = true; + +ret: + mutex_unlock(&priv->lock); + return err; +} +EXPORT_SYMBOL(max9296_setup_streaming); + +static const struct of_device_id max9296_of_match[] = { + { .compatible = "maxim,max9296", }, + { }, +}; +MODULE_DEVICE_TABLE(of, max9296_of_match); + +static int max9296_parse_dt(struct max9296 *priv, + struct i2c_client *client) +{ + struct device_node *node = client->dev.of_node; + int err = 0; + const char *str_value; + int value; + const struct of_device_id *match; + + if (!node) + return -EINVAL; + + match = of_match_device(max9296_of_match, &client->dev); + if (!match) { + dev_err(&client->dev, "Failed to find matching dt id\n"); + return -EFAULT; + } + + err = of_property_read_string(node, "csi-mode", &str_value); + if (err < 0) { + dev_err(&client->dev, "csi-mode property not found\n"); + return err; + } + + if (!strcmp(str_value, "2x4")) { + priv->csi_mode = MAX9296_CSI_MODE_2X4; + priv->lane_mp1 = MAX9296_LANE_MAP1_2X4; + priv->lane_mp2 = MAX9296_LANE_MAP2_2X4; + } else if (!strcmp(str_value, "4x2")) { + priv->csi_mode = MAX9296_CSI_MODE_4X2; + priv->lane_mp1 = MAX9296_LANE_MAP1_4X2; + priv->lane_mp2 = MAX9296_LANE_MAP2_4X2; + } else { + dev_err(&client->dev, "invalid csi mode\n"); + return -EINVAL; + } + + err = of_property_read_u32(node, "max-src", &value); + if (err < 0) { + dev_err(&client->dev, "No max-src info\n"); + return err; + } + priv->max_src = value; + + priv->reset_gpio = of_get_named_gpio(node, "reset-gpios", 0); + if (priv->reset_gpio < 0) { + dev_err(&client->dev, "reset-gpios not found %d\n", err); + return err; + } + + /* digital 1.2v */ + if (of_get_property(node, "vdd_cam_1v2-supply", NULL)) { + priv->vdd_cam_1v2 = regulator_get(&client->dev, "vdd_cam_1v2"); + if (IS_ERR(priv->vdd_cam_1v2)) { + dev_err(&client->dev, + "vdd_cam_1v2 regulator get failed\n"); + err = PTR_ERR(priv->vdd_cam_1v2); + priv->vdd_cam_1v2 = NULL; + return err; + } + } else { + priv->vdd_cam_1v2 = NULL; + } + + return 0; +} + +static struct regmap_config max9296_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, +}; + +static int max9296_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct max9296 *priv; + int err = 0; + + dev_info(&client->dev, "[MAX9296]: probing GMSL Deserializer\n"); + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + priv->i2c_client = client; + priv->regmap = devm_regmap_init_i2c(priv->i2c_client, + &max9296_regmap_config); + if (IS_ERR(priv->regmap)) { + dev_err(&client->dev, + "regmap init failed: %ld\n", PTR_ERR(priv->regmap)); + return -ENODEV; + } + + err = max9296_parse_dt(priv, client); + if (err) { + dev_err(&client->dev, "unable to parse dt\n"); + return -EFAULT; + } + + max9296_pipes_reset(priv); + + if (priv->max_src > MAX9296_MAX_SOURCES) { + dev_err(&client->dev, + "max sources more than currently supported\n"); + return -EINVAL; + } + + mutex_init(&priv->lock); + + dev_set_drvdata(&client->dev, priv); + + /* dev communication gets validated when GMSL link setup is done */ + dev_info(&client->dev, "%s: success\n", __func__); + + return 0; +} + +#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE) +static int max9296_remove(struct i2c_client *client) +#else +static void max9296_remove(struct i2c_client *client) +#endif +{ + struct max9296 *priv; + + if (client != NULL) { + priv = dev_get_drvdata(&client->dev); + mutex_destroy(&priv->lock); + i2c_unregister_device(client); + client = NULL; + } +#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE) + return 0; +#endif +} + +static const struct i2c_device_id max9296_id[] = { + { "max9296", 0 }, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, max9296_id); + +static struct i2c_driver max9296_i2c_driver = { + .driver = { + .name = "max9296", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(max9296_of_match), + }, + .probe = max9296_probe, + .remove = max9296_remove, + .id_table = max9296_id, +}; + +module_i2c_driver(max9296_i2c_driver); + +MODULE_DESCRIPTION("Dual GMSL Deserializer driver max9296"); +MODULE_AUTHOR("Sudhir Vyas +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include "imx390_mode_tbls.h" + +#define IMX390_MIN_GAIN (0) +#define IMX390_MAX_GAIN (30) +#define IMX390_MAX_GAIN_REG ((IMX390_MAX_GAIN - IMX390_MIN_GAIN) * 10 / 3) +#define IMX390_DEFAULT_FRAME_LENGTH (1125) +#define IMX390_FRAME_LENGTH_ADDR_MSB 0x200A +#define IMX390_FRAME_LENGTH_ADDR_MID 0x2009 +#define IMX390_FRAME_LENGTH_ADDR_LSB 0x2008 +#define IMX390_COARSE_TIME_SHS1_ADDR_MSB 0x000E +#define IMX390_COARSE_TIME_SHS1_ADDR_MID 0x000D +#define IMX390_COARSE_TIME_SHS1_ADDR_LSB 0x000C +#define IMX390_COARSE_TIME_SHS2_ADDR_MSB 0x0012 +#define IMX390_COARSE_TIME_SHS2_ADDR_MID 0x0011 +#define IMX390_COARSE_TIME_SHS2_ADDR_LSB 0x0010 +#define IMX390_GROUP_HOLD_ADDR 0x0008 +#define IMX390_ANALOG_GAIN_SP1H_ADDR 0x0018 +#define IMX390_ANALOG_GAIN_SP1L_ADDR 0x001A + +static const struct of_device_id imx390_of_match[] = { + { .compatible = "sony,imx390",}, + { }, +}; +MODULE_DEVICE_TABLE(of, imx390_of_match); + +static const u32 ctrl_cid_list[] = { + TEGRA_CAMERA_CID_GAIN, + TEGRA_CAMERA_CID_EXPOSURE, + TEGRA_CAMERA_CID_EXPOSURE_SHORT, + TEGRA_CAMERA_CID_FRAME_RATE, + TEGRA_CAMERA_CID_HDR_EN, +}; + +struct imx390 { + struct i2c_client *i2c_client; + const struct i2c_device_id *id; + struct v4l2_subdev *subdev; + struct device *ser_dev; + struct device *dser_dev; + struct gmsl_link_ctx g_ctx; + u32 frame_length; + struct camera_common_data *s_data; + struct tegracam_device *tc_dev; +}; + +static const struct regmap_config sensor_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, +}; + +static inline void imx390_get_frame_length_regs(imx390_reg *regs, + u32 frame_length) +{ + regs->addr = IMX390_FRAME_LENGTH_ADDR_MSB; + regs->val = (frame_length >> 16) & 0x01; + + (regs + 1)->addr = IMX390_FRAME_LENGTH_ADDR_MID; + (regs + 1)->val = (frame_length >> 8) & 0xff; + + (regs + 2)->addr = IMX390_FRAME_LENGTH_ADDR_LSB; + (regs + 2)->val = (frame_length) & 0xff; +} + +static inline void imx390_get_coarse_time_regs_shs1(imx390_reg *regs, + u32 coarse_time) +{ + regs->addr = IMX390_COARSE_TIME_SHS1_ADDR_MSB; + regs->val = (coarse_time >> 16) & 0x0f; + + (regs + 1)->addr = IMX390_COARSE_TIME_SHS1_ADDR_MID; + (regs + 1)->val = (coarse_time >> 8) & 0xff; + + (regs + 2)->addr = IMX390_COARSE_TIME_SHS1_ADDR_LSB; + (regs + 2)->val = (coarse_time) & 0xff; +} + +static inline void imx390_get_coarse_time_regs_shs2(imx390_reg *regs, + u32 coarse_time) +{ + regs->addr = IMX390_COARSE_TIME_SHS2_ADDR_MSB; + regs->val = (coarse_time >> 16) & 0x0f; + + (regs + 1)->addr = IMX390_COARSE_TIME_SHS2_ADDR_MID; + (regs + 1)->val = (coarse_time >> 8) & 0xff; + + (regs + 2)->addr = IMX390_COARSE_TIME_SHS2_ADDR_LSB; + (regs + 2)->val = (coarse_time) & 0xff; +} + +static inline void imx390_get_gain_reg(imx390_reg *regs, + u16 gain) +{ + regs->addr = IMX390_ANALOG_GAIN_SP1H_ADDR; + regs->val = (gain) & 0xff; + + (regs + 1)->addr = IMX390_ANALOG_GAIN_SP1H_ADDR + 1; + (regs + 1)->val = (gain >> 8) & 0xff; + + (regs + 2)->addr = IMX390_ANALOG_GAIN_SP1L_ADDR; + (regs + 2)->val = (gain) & 0xff; + + (regs + 3)->addr = IMX390_ANALOG_GAIN_SP1L_ADDR + 1; + (regs + 3)->val = (gain >> 8) & 0xff; +} + + +static int test_mode; +module_param(test_mode, int, 0644); + +static inline int imx390_read_reg(struct camera_common_data *s_data, + u16 addr, u8 *val) +{ + int err = 0; + u32 reg_val = 0; + + err = regmap_read(s_data->regmap, addr, ®_val); + *val = reg_val & 0xFF; + + return err; +} + +static int imx390_write_reg(struct camera_common_data *s_data, + u16 addr, u8 val) +{ + int err; + struct device *dev = s_data->dev; + + err = regmap_write(s_data->regmap, addr, val); + if (err) + dev_err(dev, "%s:i2c write failed, 0x%x = %x\n", + __func__, addr, val); + + return err; +} + +static int imx390_write_table(struct imx390 *priv, + const imx390_reg table[]) +{ + struct camera_common_data *s_data = priv->s_data; + + return regmap_util_write_table_8(s_data->regmap, + table, + NULL, 0, + IMX390_TABLE_WAIT_MS, + IMX390_TABLE_END); +} + +static struct mutex serdes_lock__; + +static int imx390_gmsl_serdes_setup(struct imx390 *priv) +{ + int err = 0; + int des_err = 0; + struct device *dev; + + if (!priv || !priv->ser_dev || !priv->dser_dev || !priv->i2c_client) + return -EINVAL; + + dev = &priv->i2c_client->dev; + + mutex_lock(&serdes_lock__); + + /* For now no separate power on required for serializer device */ + max9296_power_on(priv->dser_dev); + + /* setup serdes addressing and control pipeline */ + err = max9296_setup_link(priv->dser_dev, &priv->i2c_client->dev); + if (err) { + dev_err(dev, "gmsl deserializer link config failed\n"); + goto error; + } + + err = max9295_setup_control(priv->ser_dev); + + /* proceed even if ser setup failed, to setup deser correctly */ + if (err) + dev_err(dev, "gmsl serializer setup failed\n"); + + des_err = max9296_setup_control(priv->dser_dev, &priv->i2c_client->dev); + if (des_err) { + dev_err(dev, "gmsl deserializer setup failed\n"); + /* overwrite err only if deser setup also failed */ + err = des_err; + } + +error: + mutex_unlock(&serdes_lock__); + return err; +} + +static void imx390_gmsl_serdes_reset(struct imx390 *priv) +{ + mutex_lock(&serdes_lock__); + + /* reset serdes addressing and control pipeline */ + max9295_reset_control(priv->ser_dev); + max9296_reset_control(priv->dser_dev, &priv->i2c_client->dev); + + max9296_power_off(priv->dser_dev); + + mutex_unlock(&serdes_lock__); +} + +static int imx390_power_on(struct camera_common_data *s_data) +{ + int err = 0; + struct camera_common_power_rail *pw = s_data->power; + struct camera_common_pdata *pdata = s_data->pdata; + struct device *dev = s_data->dev; + + dev_dbg(dev, "%s: power on\n", __func__); + if (pdata && pdata->power_on) { + err = pdata->power_on(pw); + if (err) + dev_err(dev, "%s failed.\n", __func__); + else + pw->state = SWITCH_ON; + return err; + } + + pw->state = SWITCH_ON; + + return 0; +} + +static int imx390_power_off(struct camera_common_data *s_data) +{ + int err = 0; + struct camera_common_power_rail *pw = s_data->power; + struct camera_common_pdata *pdata = s_data->pdata; + struct device *dev = s_data->dev; + + dev_dbg(dev, "%s:\n", __func__); + + if (pdata && pdata->power_off) { + err = pdata->power_off(pw); + if (!err) + goto power_off_done; + else + dev_err(dev, "%s failed.\n", __func__); + return err; + } + +power_off_done: + pw->state = SWITCH_OFF; + + return 0; +} + +static int imx390_power_get(struct tegracam_device *tc_dev) +{ + struct device *dev = tc_dev->dev; + struct camera_common_data *s_data = tc_dev->s_data; + struct camera_common_power_rail *pw = s_data->power; + struct camera_common_pdata *pdata = s_data->pdata; + const char *mclk_name; + const char *parentclk_name; + struct clk *parent; + int err = 0; + + mclk_name = pdata->mclk_name ? + pdata->mclk_name : "cam_mclk1"; + pw->mclk = devm_clk_get(dev, mclk_name); + if (IS_ERR(pw->mclk)) { + dev_err(dev, "unable to get clock %s\n", mclk_name); + return PTR_ERR(pw->mclk); + } + + parentclk_name = pdata->parentclk_name; + if (parentclk_name) { + parent = devm_clk_get(dev, parentclk_name); + if (IS_ERR(parent)) { + dev_err(dev, "unable to get parent clcok %s", + parentclk_name); + } else { + err = clk_set_parent(pw->mclk, parent); + if (err < 0) + dev_dbg(dev, + "%s failed to set parent clock %d\n", + __func__, err); + } + } + + pw->state = SWITCH_OFF; + + return err; +} + +static int imx390_power_put(struct tegracam_device *tc_dev) +{ + struct camera_common_data *s_data = tc_dev->s_data; + struct camera_common_power_rail *pw = s_data->power; + + if (unlikely(!pw)) + return -EFAULT; + + return 0; +} + +static int imx390_set_group_hold(struct tegracam_device *tc_dev, bool val) +{ + struct camera_common_data *s_data = tc_dev->s_data; + struct device *dev = tc_dev->dev; + int err; + + err = imx390_write_reg(s_data, + IMX390_GROUP_HOLD_ADDR, val); + if (err) { + dev_dbg(dev, + "%s: Group hold control error\n", __func__); + return err; + } + + return 0; +} + +static int imx390_set_gain(struct tegracam_device *tc_dev, s64 val) +{ + struct camera_common_data *s_data = tc_dev->s_data; + struct device *dev = tc_dev->dev; + const struct sensor_mode_properties *mode = + &s_data->sensor_props.sensor_modes[s_data->mode_prop_idx]; + imx390_reg reg_list[4]; + int err, i; + u16 gain; + + gain = (u16)(val / mode->control_properties.step_gain_val); + + dev_dbg(dev, "%s: db: %d\n", __func__, gain); + + if (gain > IMX390_MAX_GAIN_REG) + gain = IMX390_MAX_GAIN_REG; + + imx390_get_gain_reg(reg_list, gain); + for (i = 0; i < 4; i++) { + err = imx390_write_reg(s_data, reg_list[i].addr, + reg_list[i].val); + if (err) + goto fail; + } + + return 0; + +fail: + dev_info(dev, "%s: GAIN control error\n", __func__); + return err; +} + +static int imx390_set_frame_rate(struct tegracam_device *tc_dev, s64 val) +{ + struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev); + + /* fixed 30fps */ + priv->frame_length = IMX390_DEFAULT_FRAME_LENGTH; + return 0; +} + +static int imx390_set_exposure(struct tegracam_device *tc_dev, s64 val) +{ + struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev); + struct camera_common_data *s_data = tc_dev->s_data; + const struct sensor_mode_properties *mode = + &s_data->sensor_props.sensor_modes[s_data->mode]; + imx390_reg reg_list[3]; + int err; + u32 coarse_time; + u32 shs1; + int i = 0; + + if (priv->frame_length == 0) + priv->frame_length = IMX390_DEFAULT_FRAME_LENGTH; + + /* coarse time in lines */ + coarse_time = (u32) (val * s_data->frmfmt[s_data->mode].framerates[0] * + priv->frame_length / mode->control_properties.exposure_factor); + + shs1 = priv->frame_length - coarse_time; + /* 0 and 1 are prohibited */ + if (shs1 < 2) + shs1 = 2; + + imx390_get_coarse_time_regs_shs1(reg_list, shs1); + for (i = 0; i < 3; i++) { + err = imx390_write_reg(priv->s_data, reg_list[i].addr, + reg_list[i].val); + if (err) + goto fail; + } + + imx390_get_coarse_time_regs_shs2(reg_list, shs1); + for (i = 0; i < 3; i++) { + err = imx390_write_reg(priv->s_data, reg_list[i].addr, + reg_list[i].val); + if (err) + goto fail; + } + + return 0; + +fail: + dev_dbg(&priv->i2c_client->dev, + "%s: set coarse time error\n", __func__); + return err; +} + +static struct tegracam_ctrl_ops imx390_ctrl_ops = { + .numctrls = ARRAY_SIZE(ctrl_cid_list), + .ctrl_cid_list = ctrl_cid_list, + .set_gain = imx390_set_gain, + .set_exposure = imx390_set_exposure, + .set_exposure_short = imx390_set_exposure, + .set_frame_rate = imx390_set_frame_rate, + .set_group_hold = imx390_set_group_hold, +}; + +static struct camera_common_pdata +*imx390_parse_dt(struct tegracam_device *tc_dev) +{ + struct device *dev = tc_dev->dev; + struct device_node *node = dev->of_node; + struct camera_common_pdata *board_priv_pdata; + const struct of_device_id *match; + int err; + + if (!node) + return NULL; + + match = of_match_device(imx390_of_match, dev); + if (!match) { + dev_err(dev, "Failed to find matching dt id\n"); + return NULL; + } + + board_priv_pdata = devm_kzalloc(dev, + sizeof(*board_priv_pdata), GFP_KERNEL); + + err = of_property_read_string(node, "mclk", + &board_priv_pdata->mclk_name); + if (err) + dev_err(dev, "mclk not in DT\n"); + + return board_priv_pdata; +} + +static int imx390_set_mode(struct tegracam_device *tc_dev) +{ + struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev); + struct camera_common_data *s_data = tc_dev->s_data; + struct device *dev = tc_dev->dev; + const struct of_device_id *match; + + match = of_match_device(imx390_of_match, dev); + if (!match) { + dev_err(dev, "Failed to find matching dt id\n"); + return -EINVAL; + } + + if (s_data->mode_prop_idx < 0) + return -EINVAL; + + return imx390_write_table(priv, mode_table[s_data->mode_prop_idx]); +} + +static int imx390_start_streaming(struct tegracam_device *tc_dev) +{ + struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev); + struct device *dev = tc_dev->dev; + int err; + + /* enable serdes streaming */ + err = max9295_setup_streaming(priv->ser_dev); + if (err) + goto exit; + err = max9296_setup_streaming(priv->dser_dev, dev); + if (err) + goto exit; + err = max9296_start_streaming(priv->dser_dev, dev); + if (err) + goto exit; + + err = imx390_write_table(priv, + mode_table[IMX390_MODE_START_STREAM]); + if (err) + return err; + + msleep(20); + + return 0; + +exit: + dev_err(dev, "%s: error setting stream\n", __func__); + + return err; +} + +static int imx390_stop_streaming(struct tegracam_device *tc_dev) +{ + struct device *dev = tc_dev->dev; + struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev); + + /* disable serdes streaming */ + max9296_stop_streaming(priv->dser_dev, dev); + + return imx390_write_table(priv, mode_table[IMX390_MODE_STOP_STREAM]); +} + +static struct camera_common_sensor_ops imx390_common_ops = { + .numfrmfmts = ARRAY_SIZE(imx390_frmfmt), + .frmfmt_table = imx390_frmfmt, + .power_on = imx390_power_on, + .power_off = imx390_power_off, + .write_reg = imx390_write_reg, + .read_reg = imx390_read_reg, + .parse_dt = imx390_parse_dt, + .power_get = imx390_power_get, + .power_put = imx390_power_put, + .set_mode = imx390_set_mode, + .start_streaming = imx390_start_streaming, + .stop_streaming = imx390_stop_streaming, +}; + +static int imx390_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + dev_dbg(&client->dev, "%s:\n", __func__); + + return 0; +} + +static const struct v4l2_subdev_internal_ops imx390_subdev_internal_ops = { + .open = imx390_open, +}; + +static int imx390_board_setup(struct imx390 *priv) +{ + struct tegracam_device *tc_dev = priv->tc_dev; + struct device *dev = tc_dev->dev; + struct device_node *node = dev->of_node; + struct device_node *ser_node; + struct i2c_client *ser_i2c = NULL; + struct device_node *dser_node; + struct i2c_client *dser_i2c = NULL; + struct device_node *gmsl; + int value = 0xFFFF; + const char *str_value; + const char *str_value1[2]; + int i; + int err; + + err = of_property_read_u32(node, "reg", &priv->g_ctx.sdev_reg); + if (err < 0) { + dev_err(dev, "reg not found\n"); + goto error; + } + + err = of_property_read_u32(node, "def-addr", + &priv->g_ctx.sdev_def); + if (err < 0) { + dev_err(dev, "def-addr not found\n"); + goto error; + } + + ser_node = of_parse_phandle(node, "nvidia,gmsl-ser-device", 0); + if (ser_node == NULL) { + dev_err(dev, + "missing %s handle\n", + "nvidia,gmsl-ser-device"); + err = -EINVAL; + goto error; + } + + err = of_property_read_u32(ser_node, "reg", &priv->g_ctx.ser_reg); + if (err < 0) { + dev_err(dev, "serializer reg not found\n"); + goto error; + } + + ser_i2c = of_find_i2c_device_by_node(ser_node); + of_node_put(ser_node); + + if (ser_i2c == NULL) { + err = -EPROBE_DEFER; + goto error; + } + if (ser_i2c->dev.driver == NULL) { + dev_err(dev, "missing serializer driver\n"); + err = -EINVAL; + goto error; + } + + priv->ser_dev = &ser_i2c->dev; + + dser_node = of_parse_phandle(node, "nvidia,gmsl-dser-device", 0); + if (dser_node == NULL) { + dev_err(dev, + "missing %s handle\n", + "nvidia,gmsl-dser-device"); + err = -EINVAL; + goto error; + } + + dser_i2c = of_find_i2c_device_by_node(dser_node); + of_node_put(dser_node); + + if (dser_i2c == NULL) { + err = -EPROBE_DEFER; + goto error; + } + if (dser_i2c->dev.driver == NULL) { + dev_err(dev, "missing deserializer driver\n"); + err = -EINVAL; + goto error; + } + + priv->dser_dev = &dser_i2c->dev; + + /* populate g_ctx from DT */ + gmsl = of_get_child_by_name(node, "gmsl-link"); + if (gmsl == NULL) { + dev_err(dev, "missing gmsl-link device node\n"); + err = -EINVAL; + goto error; + } + + err = of_property_read_string(gmsl, "dst-csi-port", &str_value); + if (err < 0) { + dev_err(dev, "No dst-csi-port found\n"); + goto error; + } + priv->g_ctx.dst_csi_port = + (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A : GMSL_CSI_PORT_B; + + err = of_property_read_string(gmsl, "src-csi-port", &str_value); + if (err < 0) { + dev_err(dev, "No src-csi-port found\n"); + goto error; + } + priv->g_ctx.src_csi_port = + (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A : GMSL_CSI_PORT_B; + + err = of_property_read_string(gmsl, "csi-mode", &str_value); + if (err < 0) { + dev_err(dev, "No csi-mode found\n"); + goto error; + } + + if (!strcmp(str_value, "1x4")) { + priv->g_ctx.csi_mode = GMSL_CSI_1X4_MODE; + } else if (!strcmp(str_value, "2x4")) { + priv->g_ctx.csi_mode = GMSL_CSI_2X4_MODE; + } else if (!strcmp(str_value, "4x2")) { + priv->g_ctx.csi_mode = GMSL_CSI_4X2_MODE; + } else if (!strcmp(str_value, "2x2")) { + priv->g_ctx.csi_mode = GMSL_CSI_2X2_MODE; + } else { + dev_err(dev, "invalid csi mode\n"); + err = -EINVAL; + goto error; + } + + err = of_property_read_string(gmsl, "serdes-csi-link", &str_value); + if (err < 0) { + dev_err(dev, "No serdes-csi-link found\n"); + goto error; + } + priv->g_ctx.serdes_csi_link = + (!strcmp(str_value, "a")) ? + GMSL_SERDES_CSI_LINK_A : GMSL_SERDES_CSI_LINK_B; + + err = of_property_read_u32(gmsl, "st-vc", &value); + if (err < 0) { + dev_err(dev, "No st-vc info\n"); + goto error; + } + priv->g_ctx.st_vc = value; + + err = of_property_read_u32(gmsl, "vc-id", &value); + if (err < 0) { + dev_err(dev, "No vc-id info\n"); + goto error; + } + priv->g_ctx.dst_vc = value; + + err = of_property_read_u32(gmsl, "num-lanes", &value); + if (err < 0) { + dev_err(dev, "No num-lanes info\n"); + goto error; + } + priv->g_ctx.num_csi_lanes = value; + + priv->g_ctx.num_streams = + of_property_count_strings(gmsl, "streams"); + if (priv->g_ctx.num_streams <= 0) { + dev_err(dev, "No streams found\n"); + err = -EINVAL; + goto error; + } + + for (i = 0; i < priv->g_ctx.num_streams; i++) { + of_property_read_string_index(gmsl, "streams", i, + &str_value1[i]); + if (!str_value1[i]) { + dev_err(dev, "invalid stream info\n"); + err = -EINVAL; + goto error; + } + if (!strcmp(str_value1[i], "raw12")) { + priv->g_ctx.streams[i].st_data_type = + GMSL_CSI_DT_RAW_12; + } else if (!strcmp(str_value1[i], "embed")) { + priv->g_ctx.streams[i].st_data_type = + GMSL_CSI_DT_EMBED; + } else if (!strcmp(str_value1[i], "ued-u1")) { + priv->g_ctx.streams[i].st_data_type = + GMSL_CSI_DT_UED_U1; + } else { + dev_err(dev, "invalid stream data type\n"); + err = -EINVAL; + goto error; + } + } + + priv->g_ctx.s_dev = dev; + + return 0; + +error: + return err; +} + +static int imx390_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct device_node *node = dev->of_node; + struct tegracam_device *tc_dev; + struct imx390 *priv; + int err; + + dev_info(dev, "probing v4l2 sensor.\n"); + + if (!IS_ENABLED(CONFIG_OF) || !node) + return -EINVAL; + + priv = devm_kzalloc(dev, sizeof(struct imx390), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + tc_dev = devm_kzalloc(dev, + sizeof(struct tegracam_device), GFP_KERNEL); + if (!tc_dev) + return -ENOMEM; + + priv->i2c_client = tc_dev->client = client; + tc_dev->dev = dev; + strscpy(tc_dev->name, "imx390", sizeof(tc_dev->name)); + tc_dev->dev_regmap_config = &sensor_regmap_config; + tc_dev->sensor_ops = &imx390_common_ops; + tc_dev->v4l2sd_internal_ops = &imx390_subdev_internal_ops; + tc_dev->tcctrl_ops = &imx390_ctrl_ops; + + err = tegracam_device_register(tc_dev); + if (err) { + dev_err(dev, "tegra camera driver registration failed\n"); + return err; + } + + priv->tc_dev = tc_dev; + priv->s_data = tc_dev->s_data; + priv->subdev = &tc_dev->s_data->subdev; + + tegracam_set_privdata(tc_dev, (void *)priv); + + err = imx390_board_setup(priv); + if (err) { + tegracam_device_unregister(tc_dev); + dev_err(dev, "board setup failed\n"); + return err; + } + + mutex_init(&serdes_lock__); + + /* Pair sensor to serializer dev */ + err = max9295_sdev_pair(priv->ser_dev, &priv->g_ctx); + if (err) { + dev_err(&client->dev, "gmsl ser pairing failed\n"); + return err; + } + + /* Register sensor to deserializer dev */ + err = max9296_sdev_register(priv->dser_dev, &priv->g_ctx); + if (err) { + dev_err(&client->dev, "gmsl deserializer register failed\n"); + return err; + } + + /* + * gmsl serdes setup + * + * Sensor power on/off should be the right place for serdes + * setup/reset. But the problem is, the total required delay + * in serdes setup/reset exceeds the frame wait timeout, looks to + * be related to multiple channel open and close sequence + * issue (#BUG 200477330). + * Once this bug is fixed, these may be moved to power on/off. + * The delays in serdes is as per guidelines and can't be reduced, + * so it is placed in probe/remove, though for that, deserializer + * would be powered on always post boot, until 1.2v is supplied + * to deserializer from CVB. + */ + err = imx390_gmsl_serdes_setup(priv); + if (err) { + dev_err(&client->dev, + "%s gmsl serdes setup failed\n", __func__); + return err; + } + + err = tegracam_v4l2subdev_register(tc_dev, true); + if (err) { + dev_err(dev, "tegra camera subdev registration failed\n"); + return err; + } + + dev_info(&client->dev, "Detected IMX390 sensor\n"); + + return 0; +} + +#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE) +static int imx390_remove(struct i2c_client *client) +#else +static void imx390_remove(struct i2c_client *client) +#endif +{ + struct camera_common_data *s_data = to_camera_common_data(&client->dev); + struct imx390 *priv; + + if (!s_data) +#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE) + return -EINVAL; +#else + return; +#endif + + priv = (struct imx390 *)s_data->priv; + + imx390_gmsl_serdes_reset(priv); + + mutex_destroy(&serdes_lock__); + tegracam_v4l2subdev_unregister(priv->tc_dev); + tegracam_device_unregister(priv->tc_dev); + +#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE) + return 0; +#endif +} + +static const struct i2c_device_id imx390_id[] = { + { "imx390", 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, imx390_id); + +static struct i2c_driver imx390_i2c_driver = { + .driver = { + .name = "imx390", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(imx390_of_match), + }, + .probe = imx390_probe, + .remove = imx390_remove, + .id_table = imx390_id, +}; + +module_i2c_driver(imx390_i2c_driver); + +MODULE_DESCRIPTION("Media Controller driver for Sony IMX390"); +MODULE_AUTHOR("NVIDIA Corporation"); +MODULE_AUTHOR("Sudhir Vyas