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