cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gl860-mi2020.c (30231B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* Subdriver for the GL860 chip with the MI2020 sensor
      3 * Author Olivier LORIN, from logs by Iceman/Soro2005 + Fret_saw/Hulkie/Tricid
      4 * with the help of Kytrix/BUGabundo/Blazercist.
      5 * Driver achieved thanks to a webcam gift by Kytrix.
      6 */
      7
      8/* Sensor : MI2020 */
      9
     10#include "gl860.h"
     11
     12static u8 dat_wbal1[] = {0x8c, 0xa2, 0x0c};
     13
     14static u8 dat_bright1[] = {0x8c, 0xa2, 0x06};
     15static u8 dat_bright3[] = {0x8c, 0xa1, 0x02};
     16static u8 dat_bright4[] = {0x90, 0x00, 0x0f};
     17static u8 dat_bright5[] = {0x8c, 0xa1, 0x03};
     18static u8 dat_bright6[] = {0x90, 0x00, 0x05};
     19
     20static u8 dat_hvflip1[] = {0x8c, 0x27, 0x19};
     21static u8 dat_hvflip3[] = {0x8c, 0x27, 0x3b};
     22static u8 dat_hvflip5[] = {0x8c, 0xa1, 0x03};
     23static u8 dat_hvflip6[] = {0x90, 0x00, 0x06};
     24
     25static struct idxdata tbl_middle_hvflip_low[] = {
     26	{0x33, {0x90, 0x00, 0x06}},
     27	{6, {0xff, 0xff, 0xff}},
     28	{0x33, {0x90, 0x00, 0x06}},
     29	{6, {0xff, 0xff, 0xff}},
     30	{0x33, {0x90, 0x00, 0x06}},
     31	{6, {0xff, 0xff, 0xff}},
     32	{0x33, {0x90, 0x00, 0x06}},
     33	{6, {0xff, 0xff, 0xff}},
     34};
     35
     36static struct idxdata tbl_middle_hvflip_big[] = {
     37	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x01}},
     38	{0x33, {0x8c, 0xa1, 0x20}}, {0x33, {0x90, 0x00, 0x00}},
     39	{0x33, {0x8c, 0xa7, 0x02}}, {0x33, {0x90, 0x00, 0x00}},
     40	{102, {0xff, 0xff, 0xff}},
     41	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x02}},
     42	{0x33, {0x8c, 0xa1, 0x20}}, {0x33, {0x90, 0x00, 0x72}},
     43	{0x33, {0x8c, 0xa7, 0x02}}, {0x33, {0x90, 0x00, 0x01}},
     44};
     45
     46static struct idxdata tbl_end_hvflip[] = {
     47	{0x33, {0x8c, 0xa1, 0x02}}, {0x33, {0x90, 0x00, 0x1f}},
     48	{6, {0xff, 0xff, 0xff}},
     49	{0x33, {0x8c, 0xa1, 0x02}}, {0x33, {0x90, 0x00, 0x1f}},
     50	{6, {0xff, 0xff, 0xff}},
     51	{0x33, {0x8c, 0xa1, 0x02}}, {0x33, {0x90, 0x00, 0x1f}},
     52	{6, {0xff, 0xff, 0xff}},
     53	{0x33, {0x8c, 0xa1, 0x02}}, {0x33, {0x90, 0x00, 0x1f}},
     54};
     55
     56static u8 dat_freq1[] = { 0x8c, 0xa4, 0x04 };
     57
     58static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 };
     59static u8 dat_multi6[] = { 0x90, 0x00, 0x05 };
     60
     61static struct validx tbl_init_at_startup[] = {
     62	{0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
     63	{0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
     64	{53, 0xffff},
     65	{0x0040, 0x0000}, {0x0063, 0x0006},
     66};
     67
     68static struct validx tbl_common_0B[] = {
     69	{0x0002, 0x0004}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d},
     70	{0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2},
     71	{0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000},
     72};
     73
     74static struct idxdata tbl_common_3B[] = {
     75	{0x33, {0x86, 0x25, 0x01}}, {0x33, {0x86, 0x25, 0x00}},
     76	{2, {0xff, 0xff, 0xff}},
     77	{0x30, {0x1a, 0x0a, 0xcc}}, {0x32, {0x02, 0x00, 0x08}},
     78	{0x33, {0xf4, 0x03, 0x1d}},
     79	{6, {0xff, 0xff, 0xff}}, /* 12 */
     80	{0x34, {0x1e, 0x8f, 0x09}}, {0x34, {0x1c, 0x01, 0x28}},
     81	{0x34, {0x1e, 0x8f, 0x09}},
     82	{2, {0xff, 0xff, 0xff}}, /* - */
     83	{0x34, {0x1e, 0x8f, 0x09}}, {0x32, {0x14, 0x06, 0xe6}},
     84	{0x33, {0x8c, 0x22, 0x23}}, {0x33, {0x90, 0x00, 0x00}},
     85	{0x33, {0x8c, 0xa2, 0x0f}}, {0x33, {0x90, 0x00, 0x0d}},
     86	{0x33, {0x8c, 0xa2, 0x10}}, {0x33, {0x90, 0x00, 0x0b}},
     87	{0x33, {0x8c, 0xa2, 0x11}}, {0x33, {0x90, 0x00, 0x07}},
     88	{0x33, {0xf4, 0x03, 0x1d}}, {0x35, {0xa2, 0x00, 0xe2}},
     89	{0x33, {0x8c, 0xab, 0x05}}, {0x33, {0x90, 0x00, 0x01}},
     90	{0x32, {0x6e, 0x00, 0x86}}, {0x32, {0x70, 0x0f, 0xaa}},
     91	{0x32, {0x72, 0x0f, 0xe4}}, {0x33, {0x8c, 0xa3, 0x4a}},
     92	{0x33, {0x90, 0x00, 0x5a}}, {0x33, {0x8c, 0xa3, 0x4b}},
     93	{0x33, {0x90, 0x00, 0xa6}}, {0x33, {0x8c, 0xa3, 0x61}},
     94	{0x33, {0x90, 0x00, 0xc8}}, {0x33, {0x8c, 0xa3, 0x62}},
     95	{0x33, {0x90, 0x00, 0xe1}}, {0x34, {0xce, 0x01, 0xa8}},
     96	{0x34, {0xd0, 0x66, 0x33}}, {0x34, {0xd2, 0x31, 0x9a}},
     97	{0x34, {0xd4, 0x94, 0x63}}, {0x34, {0xd6, 0x4b, 0x25}},
     98	{0x34, {0xd8, 0x26, 0x70}}, {0x34, {0xda, 0x72, 0x4c}},
     99	{0x34, {0xdc, 0xff, 0x04}}, {0x34, {0xde, 0x01, 0x5b}},
    100	{0x34, {0xe6, 0x01, 0x13}}, {0x34, {0xee, 0x0b, 0xf0}},
    101	{0x34, {0xf6, 0x0b, 0xa4}}, {0x35, {0x00, 0xf6, 0xe7}},
    102	{0x35, {0x08, 0x0d, 0xfd}}, {0x35, {0x10, 0x25, 0x63}},
    103	{0x35, {0x18, 0x35, 0x6c}}, {0x35, {0x20, 0x42, 0x7e}},
    104	{0x35, {0x28, 0x19, 0x44}}, {0x35, {0x30, 0x39, 0xd4}},
    105	{0x35, {0x38, 0xf5, 0xa8}}, {0x35, {0x4c, 0x07, 0x90}},
    106	{0x35, {0x44, 0x07, 0xb8}}, {0x35, {0x5c, 0x06, 0x88}},
    107	{0x35, {0x54, 0x07, 0xff}}, {0x34, {0xe0, 0x01, 0x52}},
    108	{0x34, {0xe8, 0x00, 0xcc}}, {0x34, {0xf0, 0x0d, 0x83}},
    109	{0x34, {0xf8, 0x0c, 0xb3}}, {0x35, {0x02, 0xfe, 0xba}},
    110	{0x35, {0x0a, 0x04, 0xe0}}, {0x35, {0x12, 0x1c, 0x63}},
    111	{0x35, {0x1a, 0x2b, 0x5a}}, {0x35, {0x22, 0x32, 0x5e}},
    112	{0x35, {0x2a, 0x0d, 0x28}}, {0x35, {0x32, 0x2c, 0x02}},
    113	{0x35, {0x3a, 0xf4, 0xfa}}, {0x35, {0x4e, 0x07, 0xef}},
    114	{0x35, {0x46, 0x07, 0x88}}, {0x35, {0x5e, 0x07, 0xc1}},
    115	{0x35, {0x56, 0x04, 0x64}}, {0x34, {0xe4, 0x01, 0x15}},
    116	{0x34, {0xec, 0x00, 0x82}}, {0x34, {0xf4, 0x0c, 0xce}},
    117	{0x34, {0xfc, 0x0c, 0xba}}, {0x35, {0x06, 0x1f, 0x02}},
    118	{0x35, {0x0e, 0x02, 0xe3}}, {0x35, {0x16, 0x1a, 0x50}},
    119	{0x35, {0x1e, 0x24, 0x39}}, {0x35, {0x26, 0x23, 0x4c}},
    120	{0x35, {0x2e, 0xf9, 0x1b}}, {0x35, {0x36, 0x23, 0x19}},
    121	{0x35, {0x3e, 0x12, 0x08}}, {0x35, {0x52, 0x07, 0x22}},
    122	{0x35, {0x4a, 0x03, 0xd3}}, {0x35, {0x62, 0x06, 0x54}},
    123	{0x35, {0x5a, 0x04, 0x5d}}, {0x34, {0xe2, 0x01, 0x04}},
    124	{0x34, {0xea, 0x00, 0xa0}}, {0x34, {0xf2, 0x0c, 0xbc}},
    125	{0x34, {0xfa, 0x0c, 0x5b}}, {0x35, {0x04, 0x17, 0xf2}},
    126	{0x35, {0x0c, 0x02, 0x08}}, {0x35, {0x14, 0x28, 0x43}},
    127	{0x35, {0x1c, 0x28, 0x62}}, {0x35, {0x24, 0x2b, 0x60}},
    128	{0x35, {0x2c, 0x07, 0x33}}, {0x35, {0x34, 0x1f, 0xb0}},
    129	{0x35, {0x3c, 0xed, 0xcd}}, {0x35, {0x50, 0x00, 0x06}},
    130	{0x35, {0x48, 0x07, 0xff}}, {0x35, {0x60, 0x05, 0x89}},
    131	{0x35, {0x58, 0x07, 0xff}}, {0x35, {0x40, 0x00, 0xa0}},
    132	{0x35, {0x42, 0x00, 0x00}}, {0x32, {0x10, 0x01, 0xfc}},
    133	{0x33, {0x8c, 0xa1, 0x18}}, {0x33, {0x90, 0x00, 0x3c}},
    134	{0x33, {0x78, 0x00, 0x00}},
    135	{2, {0xff, 0xff, 0xff}},
    136	{0x35, {0xb8, 0x1f, 0x20}}, {0x33, {0x8c, 0xa2, 0x06}},
    137	{0x33, {0x90, 0x00, 0x10}}, {0x33, {0x8c, 0xa2, 0x07}},
    138	{0x33, {0x90, 0x00, 0x08}}, {0x33, {0x8c, 0xa2, 0x42}},
    139	{0x33, {0x90, 0x00, 0x0b}}, {0x33, {0x8c, 0xa2, 0x4a}},
    140	{0x33, {0x90, 0x00, 0x8c}}, {0x35, {0xba, 0xfa, 0x08}},
    141	{0x33, {0x8c, 0xa2, 0x02}}, {0x33, {0x90, 0x00, 0x22}},
    142	{0x33, {0x8c, 0xa2, 0x03}}, {0x33, {0x90, 0x00, 0xbb}},
    143	{0x33, {0x8c, 0xa4, 0x04}}, {0x33, {0x90, 0x00, 0x80}},
    144	{0x33, {0x8c, 0xa7, 0x9d}}, {0x33, {0x90, 0x00, 0x00}},
    145	{0x33, {0x8c, 0xa7, 0x9e}}, {0x33, {0x90, 0x00, 0x00}},
    146	{0x33, {0x8c, 0xa2, 0x0c}}, {0x33, {0x90, 0x00, 0x17}},
    147	{0x33, {0x8c, 0xa2, 0x15}}, {0x33, {0x90, 0x00, 0x04}},
    148	{0x33, {0x8c, 0xa2, 0x14}}, {0x33, {0x90, 0x00, 0x20}},
    149	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x00}},
    150	{0x33, {0x8c, 0x27, 0x17}}, {0x33, {0x90, 0x21, 0x11}},
    151	{0x33, {0x8c, 0x27, 0x1b}}, {0x33, {0x90, 0x02, 0x4f}},
    152	{0x33, {0x8c, 0x27, 0x25}}, {0x33, {0x90, 0x06, 0x0f}},
    153	{0x33, {0x8c, 0x27, 0x39}}, {0x33, {0x90, 0x21, 0x11}},
    154	{0x33, {0x8c, 0x27, 0x3d}}, {0x33, {0x90, 0x01, 0x20}},
    155	{0x33, {0x8c, 0x27, 0x47}}, {0x33, {0x90, 0x09, 0x4c}},
    156	{0x33, {0x8c, 0x27, 0x03}}, {0x33, {0x90, 0x02, 0x84}},
    157	{0x33, {0x8c, 0x27, 0x05}}, {0x33, {0x90, 0x01, 0xe2}},
    158	{0x33, {0x8c, 0x27, 0x07}}, {0x33, {0x90, 0x06, 0x40}},
    159	{0x33, {0x8c, 0x27, 0x09}}, {0x33, {0x90, 0x04, 0xb0}},
    160	{0x33, {0x8c, 0x27, 0x0d}}, {0x33, {0x90, 0x00, 0x00}},
    161	{0x33, {0x8c, 0x27, 0x0f}}, {0x33, {0x90, 0x00, 0x00}},
    162	{0x33, {0x8c, 0x27, 0x11}}, {0x33, {0x90, 0x04, 0xbd}},
    163	{0x33, {0x8c, 0x27, 0x13}}, {0x33, {0x90, 0x06, 0x4d}},
    164	{0x33, {0x8c, 0x27, 0x15}}, {0x33, {0x90, 0x00, 0x00}},
    165	{0x33, {0x8c, 0x27, 0x17}}, {0x33, {0x90, 0x21, 0x11}},
    166	{0x33, {0x8c, 0x27, 0x19}}, {0x33, {0x90, 0x04, 0x6c}},
    167	{0x33, {0x8c, 0x27, 0x1b}}, {0x33, {0x90, 0x02, 0x4f}},
    168	{0x33, {0x8c, 0x27, 0x1d}}, {0x33, {0x90, 0x01, 0x02}},
    169	{0x33, {0x8c, 0x27, 0x1f}}, {0x33, {0x90, 0x02, 0x79}},
    170	{0x33, {0x8c, 0x27, 0x21}}, {0x33, {0x90, 0x01, 0x55}},
    171	{0x33, {0x8c, 0x27, 0x23}}, {0x33, {0x90, 0x02, 0x85}},
    172	{0x33, {0x8c, 0x27, 0x25}}, {0x33, {0x90, 0x06, 0x0f}},
    173	{0x33, {0x8c, 0x27, 0x27}}, {0x33, {0x90, 0x20, 0x20}},
    174	{0x33, {0x8c, 0x27, 0x29}}, {0x33, {0x90, 0x20, 0x20}},
    175	{0x33, {0x8c, 0x27, 0x2b}}, {0x33, {0x90, 0x10, 0x20}},
    176	{0x33, {0x8c, 0x27, 0x2d}}, {0x33, {0x90, 0x20, 0x07}},
    177	{0x33, {0x8c, 0x27, 0x2f}}, {0x33, {0x90, 0x00, 0x04}},
    178	{0x33, {0x8c, 0x27, 0x31}}, {0x33, {0x90, 0x00, 0x04}},
    179	{0x33, {0x8c, 0x27, 0x33}}, {0x33, {0x90, 0x04, 0xbb}},
    180	{0x33, {0x8c, 0x27, 0x35}}, {0x33, {0x90, 0x06, 0x4b}},
    181	{0x33, {0x8c, 0x27, 0x37}}, {0x33, {0x90, 0x00, 0x00}},
    182	{0x33, {0x8c, 0x27, 0x39}}, {0x33, {0x90, 0x21, 0x11}},
    183	{0x33, {0x8c, 0x27, 0x3b}}, {0x33, {0x90, 0x00, 0x24}},
    184	{0x33, {0x8c, 0x27, 0x3d}}, {0x33, {0x90, 0x01, 0x20}},
    185	{0x33, {0x8c, 0x27, 0x41}}, {0x33, {0x90, 0x01, 0x69}},
    186	{0x33, {0x8c, 0x27, 0x45}}, {0x33, {0x90, 0x04, 0xed}},
    187	{0x33, {0x8c, 0x27, 0x47}}, {0x33, {0x90, 0x09, 0x4c}},
    188	{0x33, {0x8c, 0x27, 0x51}}, {0x33, {0x90, 0x00, 0x00}},
    189	{0x33, {0x8c, 0x27, 0x53}}, {0x33, {0x90, 0x03, 0x20}},
    190	{0x33, {0x8c, 0x27, 0x55}}, {0x33, {0x90, 0x00, 0x00}},
    191	{0x33, {0x8c, 0x27, 0x57}}, {0x33, {0x90, 0x02, 0x58}},
    192	{0x33, {0x8c, 0x27, 0x5f}}, {0x33, {0x90, 0x00, 0x00}},
    193	{0x33, {0x8c, 0x27, 0x61}}, {0x33, {0x90, 0x06, 0x40}},
    194	{0x33, {0x8c, 0x27, 0x63}}, {0x33, {0x90, 0x00, 0x00}},
    195	{0x33, {0x8c, 0x27, 0x65}}, {0x33, {0x90, 0x04, 0xb0}},
    196	{0x33, {0x8c, 0x22, 0x2e}}, {0x33, {0x90, 0x00, 0xa1}},
    197	{0x33, {0x8c, 0xa4, 0x08}}, {0x33, {0x90, 0x00, 0x1f}},
    198	{0x33, {0x8c, 0xa4, 0x09}}, {0x33, {0x90, 0x00, 0x21}},
    199	{0x33, {0x8c, 0xa4, 0x0a}}, {0x33, {0x90, 0x00, 0x25}},
    200	{0x33, {0x8c, 0xa4, 0x0b}}, {0x33, {0x90, 0x00, 0x27}},
    201	{0x33, {0x8c, 0x24, 0x11}}, {0x33, {0x90, 0x00, 0xa1}},
    202	{0x33, {0x8c, 0x24, 0x13}}, {0x33, {0x90, 0x00, 0xc1}},
    203	{0x33, {0x8c, 0x24, 0x15}}, {0x33, {0x90, 0x00, 0x6a}},
    204	{0x33, {0x8c, 0x24, 0x17}}, {0x33, {0x90, 0x00, 0x80}},
    205	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x05}},
    206	{2, {0xff, 0xff, 0xff}},
    207	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x06}},
    208	{3, {0xff, 0xff, 0xff}},
    209};
    210
    211static struct idxdata tbl_init_post_alt_low1[] = {
    212	{0x33, {0x8c, 0x27, 0x15}}, {0x33, {0x90, 0x00, 0x25}},
    213	{0x33, {0x8c, 0x22, 0x2e}}, {0x33, {0x90, 0x00, 0x81}},
    214	{0x33, {0x8c, 0xa4, 0x08}}, {0x33, {0x90, 0x00, 0x17}},
    215	{0x33, {0x8c, 0xa4, 0x09}}, {0x33, {0x90, 0x00, 0x1a}},
    216	{0x33, {0x8c, 0xa4, 0x0a}}, {0x33, {0x90, 0x00, 0x1d}},
    217	{0x33, {0x8c, 0xa4, 0x0b}}, {0x33, {0x90, 0x00, 0x20}},
    218	{0x33, {0x8c, 0x24, 0x11}}, {0x33, {0x90, 0x00, 0x81}},
    219	{0x33, {0x8c, 0x24, 0x13}}, {0x33, {0x90, 0x00, 0x9b}},
    220};
    221
    222static struct idxdata tbl_init_post_alt_low2[] = {
    223	{0x33, {0x8c, 0x27, 0x03}}, {0x33, {0x90, 0x03, 0x24}},
    224	{0x33, {0x8c, 0x27, 0x05}}, {0x33, {0x90, 0x02, 0x58}},
    225	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x05}},
    226	{2, {0xff, 0xff, 0xff}},
    227	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x06}},
    228	{2, {0xff, 0xff, 0xff}},
    229};
    230
    231static struct idxdata tbl_init_post_alt_low3[] = {
    232	{0x34, {0x1e, 0x8f, 0x09}}, {0x34, {0x1c, 0x01, 0x28}},
    233	{0x34, {0x1e, 0x8f, 0x09}},
    234	{2, {0xff, 0xff, 0xff}},
    235	{0x34, {0x1e, 0x8f, 0x09}}, {0x32, {0x14, 0x06, 0xe6}},
    236	{0x33, {0x8c, 0xa1, 0x20}}, {0x33, {0x90, 0x00, 0x00}},
    237	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x01}},
    238	{0x33, {0x2e, 0x01, 0x00}}, {0x34, {0x04, 0x00, 0x2a}},
    239	{0x33, {0x8c, 0xa7, 0x02}}, {0x33, {0x90, 0x00, 0x00}},
    240	{0x33, {0x8c, 0x27, 0x95}}, {0x33, {0x90, 0x01, 0x00}},
    241	{2, {0xff, 0xff, 0xff}},
    242	{0x33, {0x8c, 0xa1, 0x20}}, {0x33, {0x90, 0x00, 0x72}},
    243	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x02}},
    244	{0x33, {0x8c, 0xa7, 0x02}}, {0x33, {0x90, 0x00, 0x01}},
    245	{2, {0xff, 0xff, 0xff}},
    246	{0x33, {0x8c, 0xa1, 0x20}}, {0x33, {0x90, 0x00, 0x00}},
    247	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x01}},
    248	{0x33, {0x8c, 0xa7, 0x02}}, {0x33, {0x90, 0x00, 0x00}},
    249	{2, {0xff, 0xff, 0xff}},
    250	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x05}},
    251	{2, {0xff, 0xff, 0xff}},
    252	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x06}},
    253	{2, {0xff, 0xff, 0xff}},
    254	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x05}},
    255	{2, {0xff, 0xff, 0xff}},
    256	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x06}},
    257};
    258
    259static struct idxdata tbl_init_post_alt_big[] = {
    260	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x05}},
    261	{2, {0xff, 0xff, 0xff}},
    262	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x06}},
    263	{2, {0xff, 0xff, 0xff}},
    264	{0x34, {0x1e, 0x8f, 0x09}}, {0x34, {0x1c, 0x01, 0x28}},
    265	{0x34, {0x1e, 0x8f, 0x09}},
    266	{2, {0xff, 0xff, 0xff}},
    267	{0x34, {0x1e, 0x8f, 0x09}}, {0x32, {0x14, 0x06, 0xe6}},
    268	{0x33, {0x8c, 0xa1, 0x03}},
    269	{0x33, {0x90, 0x00, 0x05}},
    270	{2, {0xff, 0xff, 0xff}},
    271	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x06}},
    272	{2, {0xff, 0xff, 0xff}},
    273	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x05}},
    274	{2, {0xff, 0xff, 0xff}},
    275	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x06}},
    276	{0x33, {0x8c, 0xa1, 0x20}}, {0x33, {0x90, 0x00, 0x72}},
    277	{0x33, {0x8c, 0xa1, 0x30}}, {0x33, {0x90, 0x00, 0x03}},
    278	{0x33, {0x8c, 0xa1, 0x31}}, {0x33, {0x90, 0x00, 0x02}},
    279	{0x33, {0x8c, 0xa1, 0x32}}, {0x33, {0x90, 0x00, 0x03}},
    280	{0x33, {0x8c, 0xa1, 0x34}}, {0x33, {0x90, 0x00, 0x03}},
    281	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x02}},
    282	{0x33, {0x2e, 0x01, 0x00}}, {0x34, {0x04, 0x00, 0x2a}},
    283	{0x33, {0x8c, 0xa7, 0x02}}, {0x33, {0x90, 0x00, 0x01}},
    284	{0x33, {0x8c, 0x27, 0x97}}, {0x33, {0x90, 0x01, 0x00}},
    285	{51, {0xff, 0xff, 0xff}},
    286	{0x33, {0x8c, 0xa1, 0x20}}, {0x33, {0x90, 0x00, 0x00}},
    287	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x01}},
    288	{0x33, {0x8c, 0xa7, 0x02}}, {0x33, {0x90, 0x00, 0x00}},
    289	{51, {0xff, 0xff, 0xff}},
    290	{0x33, {0x8c, 0xa1, 0x20}}, {0x33, {0x90, 0x00, 0x72}},
    291	{0x33, {0x8c, 0xa1, 0x03}}, {0x33, {0x90, 0x00, 0x02}},
    292	{0x33, {0x8c, 0xa7, 0x02}}, {0x33, {0x90, 0x00, 0x01}},
    293	{51, {0xff, 0xff, 0xff}},
    294};
    295
    296static struct idxdata tbl_init_post_alt_3B[] = {
    297	{0x32, {0x10, 0x01, 0xf8}}, {0x34, {0xce, 0x01, 0xa8}},
    298	{0x34, {0xd0, 0x66, 0x33}}, {0x34, {0xd2, 0x31, 0x9a}},
    299	{0x34, {0xd4, 0x94, 0x63}}, {0x34, {0xd6, 0x4b, 0x25}},
    300	{0x34, {0xd8, 0x26, 0x70}}, {0x34, {0xda, 0x72, 0x4c}},
    301	{0x34, {0xdc, 0xff, 0x04}}, {0x34, {0xde, 0x01, 0x5b}},
    302	{0x34, {0xe6, 0x01, 0x13}}, {0x34, {0xee, 0x0b, 0xf0}},
    303	{0x34, {0xf6, 0x0b, 0xa4}}, {0x35, {0x00, 0xf6, 0xe7}},
    304	{0x35, {0x08, 0x0d, 0xfd}}, {0x35, {0x10, 0x25, 0x63}},
    305	{0x35, {0x18, 0x35, 0x6c}}, {0x35, {0x20, 0x42, 0x7e}},
    306	{0x35, {0x28, 0x19, 0x44}}, {0x35, {0x30, 0x39, 0xd4}},
    307	{0x35, {0x38, 0xf5, 0xa8}}, {0x35, {0x4c, 0x07, 0x90}},
    308	{0x35, {0x44, 0x07, 0xb8}}, {0x35, {0x5c, 0x06, 0x88}},
    309	{0x35, {0x54, 0x07, 0xff}}, {0x34, {0xe0, 0x01, 0x52}},
    310	{0x34, {0xe8, 0x00, 0xcc}}, {0x34, {0xf0, 0x0d, 0x83}},
    311	{0x34, {0xf8, 0x0c, 0xb3}}, {0x35, {0x02, 0xfe, 0xba}},
    312	{0x35, {0x0a, 0x04, 0xe0}}, {0x35, {0x12, 0x1c, 0x63}},
    313	{0x35, {0x1a, 0x2b, 0x5a}}, {0x35, {0x22, 0x32, 0x5e}},
    314	{0x35, {0x2a, 0x0d, 0x28}}, {0x35, {0x32, 0x2c, 0x02}},
    315	{0x35, {0x3a, 0xf4, 0xfa}}, {0x35, {0x4e, 0x07, 0xef}},
    316	{0x35, {0x46, 0x07, 0x88}}, {0x35, {0x5e, 0x07, 0xc1}},
    317	{0x35, {0x56, 0x04, 0x64}}, {0x34, {0xe4, 0x01, 0x15}},
    318	{0x34, {0xec, 0x00, 0x82}}, {0x34, {0xf4, 0x0c, 0xce}},
    319	{0x34, {0xfc, 0x0c, 0xba}}, {0x35, {0x06, 0x1f, 0x02}},
    320	{0x35, {0x0e, 0x02, 0xe3}}, {0x35, {0x16, 0x1a, 0x50}},
    321	{0x35, {0x1e, 0x24, 0x39}}, {0x35, {0x26, 0x23, 0x4c}},
    322	{0x35, {0x2e, 0xf9, 0x1b}}, {0x35, {0x36, 0x23, 0x19}},
    323	{0x35, {0x3e, 0x12, 0x08}}, {0x35, {0x52, 0x07, 0x22}},
    324	{0x35, {0x4a, 0x03, 0xd3}}, {0x35, {0x62, 0x06, 0x54}},
    325	{0x35, {0x5a, 0x04, 0x5d}}, {0x34, {0xe2, 0x01, 0x04}},
    326	{0x34, {0xea, 0x00, 0xa0}}, {0x34, {0xf2, 0x0c, 0xbc}},
    327	{0x34, {0xfa, 0x0c, 0x5b}}, {0x35, {0x04, 0x17, 0xf2}},
    328	{0x35, {0x0c, 0x02, 0x08}}, {0x35, {0x14, 0x28, 0x43}},
    329	{0x35, {0x1c, 0x28, 0x62}}, {0x35, {0x24, 0x2b, 0x60}},
    330	{0x35, {0x2c, 0x07, 0x33}}, {0x35, {0x34, 0x1f, 0xb0}},
    331	{0x35, {0x3c, 0xed, 0xcd}}, {0x35, {0x50, 0x00, 0x06}},
    332	{0x35, {0x48, 0x07, 0xff}}, {0x35, {0x60, 0x05, 0x89}},
    333	{0x35, {0x58, 0x07, 0xff}}, {0x35, {0x40, 0x00, 0xa0}},
    334	{0x35, {0x42, 0x00, 0x00}}, {0x32, {0x10, 0x01, 0xfc}},
    335	{0x33, {0x8c, 0xa1, 0x18}}, {0x33, {0x90, 0x00, 0x3c}},
    336};
    337
    338static u8 *dat_640  = "\xd0\x02\xd1\x08\xd2\xe1\xd3\x02\xd4\x10\xd5\x81";
    339static u8 *dat_800  = "\xd0\x02\xd1\x10\xd2\x57\xd3\x02\xd4\x18\xd5\x21";
    340static u8 *dat_1280 = "\xd0\x02\xd1\x20\xd2\x01\xd3\x02\xd4\x28\xd5\x01";
    341static u8 *dat_1600 = "\xd0\x02\xd1\x20\xd2\xaf\xd3\x02\xd4\x30\xd5\x41";
    342
    343static int  mi2020_init_at_startup(struct gspca_dev *gspca_dev);
    344static int  mi2020_configure_alt(struct gspca_dev *gspca_dev);
    345static int  mi2020_init_pre_alt(struct gspca_dev *gspca_dev);
    346static int  mi2020_init_post_alt(struct gspca_dev *gspca_dev);
    347static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev);
    348static int  mi2020_camera_settings(struct gspca_dev *gspca_dev);
    349/*==========================================================================*/
    350
    351void mi2020_init_settings(struct gspca_dev *gspca_dev)
    352{
    353	struct sd *sd = (struct sd *) gspca_dev;
    354
    355	sd->vcur.backlight  =  0;
    356	sd->vcur.brightness = 70;
    357	sd->vcur.sharpness  = 20;
    358	sd->vcur.contrast   =  0;
    359	sd->vcur.gamma      =  0;
    360	sd->vcur.hue        =  0;
    361	sd->vcur.saturation = 60;
    362	sd->vcur.whitebal   =  0; /* 50, not done by hardware */
    363	sd->vcur.mirror = 0;
    364	sd->vcur.flip   = 0;
    365	sd->vcur.AC50Hz = 1;
    366
    367	sd->vmax.backlight  =  64;
    368	sd->vmax.brightness = 128;
    369	sd->vmax.sharpness  =  40;
    370	sd->vmax.contrast   =   3;
    371	sd->vmax.gamma      =   2;
    372	sd->vmax.hue        =   0 + 1; /* 200, not done by hardware */
    373	sd->vmax.saturation =   0;     /* 100, not done by hardware */
    374	sd->vmax.whitebal   =   2;     /* 100, not done by hardware */
    375	sd->vmax.mirror = 1;
    376	sd->vmax.flip   = 1;
    377	sd->vmax.AC50Hz = 1;
    378
    379	sd->dev_camera_settings = mi2020_camera_settings;
    380	sd->dev_init_at_startup = mi2020_init_at_startup;
    381	sd->dev_configure_alt   = mi2020_configure_alt;
    382	sd->dev_init_pre_alt    = mi2020_init_pre_alt;
    383	sd->dev_post_unset_alt  = mi2020_post_unset_alt;
    384}
    385
    386/*==========================================================================*/
    387
    388static void common(struct gspca_dev *gspca_dev)
    389{
    390	fetch_validx(gspca_dev, tbl_common_0B, ARRAY_SIZE(tbl_common_0B));
    391	fetch_idxdata(gspca_dev, tbl_common_3B, ARRAY_SIZE(tbl_common_3B));
    392	ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL);
    393}
    394
    395static int mi2020_init_at_startup(struct gspca_dev *gspca_dev)
    396{
    397	u8 c;
    398
    399	ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c);
    400	ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c);
    401
    402	fetch_validx(gspca_dev, tbl_init_at_startup,
    403			ARRAY_SIZE(tbl_init_at_startup));
    404
    405	ctrl_out(gspca_dev, 0x40,  1, 0x7a00, 0x8030,  0, NULL);
    406	ctrl_in(gspca_dev, 0xc0,  2, 0x7a00, 0x8030,  1, &c);
    407
    408	common(gspca_dev);
    409
    410	msleep(61);
    411/*	ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000,  0, NULL); */
    412/*	msleep(36); */
    413	ctrl_out(gspca_dev, 0x40,  1, 0x0001, 0x0000,  0, NULL);
    414
    415	return 0;
    416}
    417
    418static int mi2020_init_pre_alt(struct gspca_dev *gspca_dev)
    419{
    420	struct sd *sd = (struct sd *) gspca_dev;
    421
    422	sd->mirrorMask =  0;
    423	sd->vold.hue   = -1;
    424
    425	/* These controls need to be reset */
    426	sd->vold.brightness = -1;
    427	sd->vold.sharpness  = -1;
    428
    429	/* If not different from default, they do not need to be set */
    430	sd->vold.contrast  = 0;
    431	sd->vold.gamma     = 0;
    432	sd->vold.backlight = 0;
    433
    434	mi2020_init_post_alt(gspca_dev);
    435
    436	return 0;
    437}
    438
    439static int mi2020_init_post_alt(struct gspca_dev *gspca_dev)
    440{
    441	struct sd *sd = (struct sd *) gspca_dev;
    442	s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
    443
    444	s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
    445	s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
    446	s32 freq   = (sd->vcur.AC50Hz  > 0);
    447	s32 wbal   = sd->vcur.whitebal;
    448
    449	u8 dat_freq2[] = {0x90, 0x00, 0x80};
    450	u8 dat_multi1[] = {0x8c, 0xa7, 0x00};
    451	u8 dat_multi2[] = {0x90, 0x00, 0x00};
    452	u8 dat_multi3[] = {0x8c, 0xa7, 0x00};
    453	u8 dat_multi4[] = {0x90, 0x00, 0x00};
    454	u8 dat_hvflip2[] = {0x90, 0x04, 0x6c};
    455	u8 dat_hvflip4[] = {0x90, 0x00, 0x24};
    456	u8 dat_wbal2[] = {0x90, 0x00, 0x00};
    457	u8 c;
    458
    459	sd->nbIm = -1;
    460
    461	dat_freq2[2] = freq ? 0xc0 : 0x80;
    462	dat_multi1[2] = 0x9d;
    463	dat_multi3[2] = dat_multi1[2] + 1;
    464	if (wbal == 0) {
    465		dat_multi4[2] = dat_multi2[2] = 0;
    466		dat_wbal2[2] = 0x17;
    467	} else if (wbal == 1) {
    468		dat_multi4[2] = dat_multi2[2] = 0;
    469		dat_wbal2[2] = 0x35;
    470	} else if (wbal == 2) {
    471		dat_multi4[2] = dat_multi2[2] = 0x20;
    472		dat_wbal2[2] = 0x17;
    473	}
    474	dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror);
    475	dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror);
    476
    477	msleep(200);
    478	ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
    479	msleep(2);
    480
    481	common(gspca_dev);
    482
    483	msleep(142);
    484	ctrl_out(gspca_dev, 0x40,  1, 0x0010, 0x0010,  0, NULL);
    485	ctrl_out(gspca_dev, 0x40,  1, 0x0003, 0x00c1,  0, NULL);
    486	ctrl_out(gspca_dev, 0x40,  1, 0x0042, 0x00c2,  0, NULL);
    487	ctrl_out(gspca_dev, 0x40,  1, 0x006a, 0x000d,  0, NULL);
    488
    489	switch (reso) {
    490	case IMAGE_640:
    491	case IMAGE_800:
    492		if (reso != IMAGE_800)
    493			ctrl_out(gspca_dev, 0x40,  3, 0x0000, 0x0200,
    494				12, dat_640);
    495		else
    496			ctrl_out(gspca_dev, 0x40,  3, 0x0000, 0x0200,
    497				12, dat_800);
    498
    499		fetch_idxdata(gspca_dev, tbl_init_post_alt_low1,
    500					ARRAY_SIZE(tbl_init_post_alt_low1));
    501
    502		if (reso == IMAGE_800)
    503			fetch_idxdata(gspca_dev, tbl_init_post_alt_low2,
    504					ARRAY_SIZE(tbl_init_post_alt_low2));
    505
    506		fetch_idxdata(gspca_dev, tbl_init_post_alt_low3,
    507				ARRAY_SIZE(tbl_init_post_alt_low3));
    508
    509		ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
    510		ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
    511		ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
    512		msleep(120);
    513		break;
    514
    515	case IMAGE_1280:
    516	case IMAGE_1600:
    517		if (reso == IMAGE_1280) {
    518			ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
    519					12, dat_1280);
    520			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
    521					3, "\x8c\x27\x07");
    522			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
    523					3, "\x90\x05\x04");
    524			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
    525					3, "\x8c\x27\x09");
    526			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
    527					3, "\x90\x04\x02");
    528		} else {
    529			ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
    530					12, dat_1600);
    531			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
    532					3, "\x8c\x27\x07");
    533			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
    534					3, "\x90\x06\x40");
    535			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
    536					3, "\x8c\x27\x09");
    537			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
    538					3, "\x90\x04\xb0");
    539		}
    540
    541		fetch_idxdata(gspca_dev, tbl_init_post_alt_big,
    542				ARRAY_SIZE(tbl_init_post_alt_big));
    543
    544		ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
    545		ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
    546		ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
    547		msleep(1850);
    548	}
    549
    550	ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
    551	msleep(40);
    552
    553	/* AC power frequency */
    554	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
    555	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
    556	msleep(33);
    557	/* light source */
    558	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
    559	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
    560	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
    561	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
    562	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1);
    563	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2);
    564	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
    565	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
    566	msleep(7);
    567	ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c);
    568
    569	fetch_idxdata(gspca_dev, tbl_init_post_alt_3B,
    570			ARRAY_SIZE(tbl_init_post_alt_3B));
    571
    572	/* hvflip */
    573	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1);
    574	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2);
    575	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3);
    576	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4);
    577	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5);
    578	ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6);
    579	msleep(250);
    580
    581	if (reso == IMAGE_640 || reso == IMAGE_800)
    582		fetch_idxdata(gspca_dev, tbl_middle_hvflip_low,
    583				ARRAY_SIZE(tbl_middle_hvflip_low));
    584	else
    585		fetch_idxdata(gspca_dev, tbl_middle_hvflip_big,
    586				ARRAY_SIZE(tbl_middle_hvflip_big));
    587
    588	fetch_idxdata(gspca_dev, tbl_end_hvflip,
    589			ARRAY_SIZE(tbl_end_hvflip));
    590
    591	sd->nbIm = 0;
    592
    593	sd->vold.mirror    = mirror;
    594	sd->vold.flip      = flip;
    595	sd->vold.AC50Hz    = freq;
    596	sd->vold.whitebal  = wbal;
    597
    598	mi2020_camera_settings(gspca_dev);
    599
    600	return 0;
    601}
    602
    603static int mi2020_configure_alt(struct gspca_dev *gspca_dev)
    604{
    605	s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
    606
    607	switch (reso) {
    608	case IMAGE_640:
    609		gspca_dev->alt = 3 + 1;
    610		break;
    611
    612	case IMAGE_800:
    613	case IMAGE_1280:
    614	case IMAGE_1600:
    615		gspca_dev->alt = 1 + 1;
    616		break;
    617	}
    618	return 0;
    619}
    620
    621static int mi2020_camera_settings(struct gspca_dev *gspca_dev)
    622{
    623	struct sd *sd = (struct sd *) gspca_dev;
    624	s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
    625
    626	s32 backlight = sd->vcur.backlight;
    627	s32 bright =  sd->vcur.brightness;
    628	s32 sharp  =  sd->vcur.sharpness;
    629	s32 cntr   =  sd->vcur.contrast;
    630	s32 gam	   =  sd->vcur.gamma;
    631	s32 hue    = (sd->vcur.hue > 0);
    632	s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
    633	s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
    634	s32 freq   = (sd->vcur.AC50Hz > 0);
    635	s32 wbal   = sd->vcur.whitebal;
    636
    637	u8 dat_sharp[] = {0x6c, 0x00, 0x08};
    638	u8 dat_bright2[] = {0x90, 0x00, 0x00};
    639	u8 dat_freq2[] = {0x90, 0x00, 0x80};
    640	u8 dat_multi1[] = {0x8c, 0xa7, 0x00};
    641	u8 dat_multi2[] = {0x90, 0x00, 0x00};
    642	u8 dat_multi3[] = {0x8c, 0xa7, 0x00};
    643	u8 dat_multi4[] = {0x90, 0x00, 0x00};
    644	u8 dat_hvflip2[] = {0x90, 0x04, 0x6c};
    645	u8 dat_hvflip4[] = {0x90, 0x00, 0x24};
    646	u8 dat_wbal2[] = {0x90, 0x00, 0x00};
    647
    648	/* Less than 4 images received -> too early to set the settings */
    649	if (sd->nbIm < 4) {
    650		sd->waitSet = 1;
    651		return 0;
    652	}
    653	sd->waitSet = 0;
    654
    655	if (freq != sd->vold.AC50Hz) {
    656		sd->vold.AC50Hz = freq;
    657
    658		dat_freq2[2] = freq ? 0xc0 : 0x80;
    659		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
    660		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
    661		msleep(20);
    662	}
    663
    664	if (wbal != sd->vold.whitebal) {
    665		sd->vold.whitebal = wbal;
    666		if (wbal < 0 || wbal > sd->vmax.whitebal)
    667			wbal = 0;
    668
    669		dat_multi1[2] = 0x9d;
    670		dat_multi3[2] = dat_multi1[2] + 1;
    671		if (wbal == 0) {
    672			dat_multi4[2] = dat_multi2[2] = 0;
    673			dat_wbal2[2] = 0x17;
    674		} else if (wbal == 1) {
    675			dat_multi4[2] = dat_multi2[2] = 0;
    676			dat_wbal2[2] = 0x35;
    677		} else if (wbal == 2) {
    678			dat_multi4[2] = dat_multi2[2] = 0x20;
    679			dat_wbal2[2] = 0x17;
    680		}
    681		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
    682		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
    683		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
    684		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
    685		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1);
    686		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2);
    687		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
    688		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
    689	}
    690
    691	if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
    692		sd->vold.mirror = mirror;
    693		sd->vold.flip   = flip;
    694
    695		dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror);
    696		dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror);
    697
    698		fetch_idxdata(gspca_dev, tbl_init_post_alt_3B,
    699				ARRAY_SIZE(tbl_init_post_alt_3B));
    700
    701		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1);
    702		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2);
    703		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3);
    704		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4);
    705		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5);
    706		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6);
    707		msleep(40);
    708
    709		if (reso == IMAGE_640 || reso == IMAGE_800)
    710			fetch_idxdata(gspca_dev, tbl_middle_hvflip_low,
    711					ARRAY_SIZE(tbl_middle_hvflip_low));
    712		else
    713			fetch_idxdata(gspca_dev, tbl_middle_hvflip_big,
    714					ARRAY_SIZE(tbl_middle_hvflip_big));
    715
    716		fetch_idxdata(gspca_dev, tbl_end_hvflip,
    717				ARRAY_SIZE(tbl_end_hvflip));
    718	}
    719
    720	if (bright != sd->vold.brightness) {
    721		sd->vold.brightness = bright;
    722		if (bright < 0 || bright > sd->vmax.brightness)
    723			bright = 0;
    724
    725		dat_bright2[2] = bright;
    726		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright1);
    727		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright2);
    728		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright3);
    729		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright4);
    730		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright5);
    731		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright6);
    732	}
    733
    734	if (cntr != sd->vold.contrast || gam != sd->vold.gamma) {
    735		sd->vold.contrast = cntr;
    736		if (cntr < 0 || cntr > sd->vmax.contrast)
    737			cntr = 0;
    738		sd->vold.gamma = gam;
    739		if (gam < 0 || gam > sd->vmax.gamma)
    740			gam = 0;
    741
    742		dat_multi1[2] = 0x6d;
    743		dat_multi3[2] = dat_multi1[2] + 1;
    744		if (cntr == 0)
    745			cntr = 4;
    746		dat_multi4[2] = dat_multi2[2] = cntr * 0x10 + 2 - gam;
    747		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
    748		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
    749		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
    750		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
    751		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
    752		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
    753	}
    754
    755	if (backlight != sd->vold.backlight) {
    756		sd->vold.backlight = backlight;
    757		if (backlight < 0 || backlight > sd->vmax.backlight)
    758			backlight = 0;
    759
    760		dat_multi1[2] = 0x9d;
    761		dat_multi3[2] = dat_multi1[2] + 1;
    762		dat_multi4[2] = dat_multi2[2] = backlight;
    763		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
    764		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
    765		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
    766		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
    767		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
    768		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
    769	}
    770
    771	if (sharp != sd->vold.sharpness) {
    772		sd->vold.sharpness = sharp;
    773		if (sharp < 0 || sharp > sd->vmax.sharpness)
    774			sharp = 0;
    775
    776		dat_sharp[1] = sharp;
    777		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0032, 3, dat_sharp);
    778	}
    779
    780	if (hue != sd->vold.hue) {
    781		sd->swapRB = hue;
    782		sd->vold.hue = hue;
    783	}
    784
    785	return 0;
    786}
    787
    788static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev)
    789{
    790	ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
    791	msleep(40);
    792	ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0000, 0, NULL);
    793}