linux/drivers/media/usb/gspca/gl860/gl860-mi1320.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* Subdriver for the GL860 chip with the MI1320 sensor
   3 * Author Olivier LORIN from own logs
   4 */
   5
   6/* Sensor : MI1320 */
   7
   8#include "gl860.h"
   9
  10static struct validx tbl_common[] = {
  11        {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba51, 0x0066}, {0xba02, 0x00f1},
  12        {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
  13        {0xffff, 0xffff},
  14        {0xba00, 0x00f0}, {0xba02, 0x00f1}, {0xbafa, 0x0028}, {0xba02, 0x00f1},
  15        {0xba00, 0x00f0}, {0xba01, 0x00f1}, {0xbaf0, 0x0006}, {0xba0e, 0x00f1},
  16        {0xba70, 0x0006}, {0xba0e, 0x00f1},
  17        {0xffff, 0xffff},
  18        {0xba74, 0x0006}, {0xba0e, 0x00f1},
  19        {0xffff, 0xffff},
  20        {0x0061, 0x0000}, {0x0068, 0x000d},
  21};
  22
  23static struct validx tbl_init_at_startup[] = {
  24        {0x0000, 0x0000}, {0x0010, 0x0010},
  25        {35, 0xffff},
  26        {0x0008, 0x00c0}, {0x0001, 0x00c1}, {0x0001, 0x00c2}, {0x0020, 0x0006},
  27        {0x006a, 0x000d},
  28};
  29
  30static struct validx tbl_sensor_settings_common[] = {
  31        {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, {0x0040, 0x0000},
  32        {0x006a, 0x0007}, {0x006a, 0x000d}, {0x0063, 0x0006},
  33};
  34static struct validx tbl_sensor_settings_1280[] = {
  35        {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
  36        {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
  37};
  38static struct validx tbl_sensor_settings_800[] = {
  39        {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
  40        {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
  41};
  42static struct validx tbl_sensor_settings_640[] = {
  43        {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
  44        {0xba51, 0x0066}, {0xba02, 0x00f1}, {0xba05, 0x0067}, {0xba05, 0x00f1},
  45        {0xba20, 0x0065}, {0xba00, 0x00f1},
  46};
  47static struct validx tbl_post_unset_alt[] = {
  48        {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
  49        {0x0061, 0x0000}, {0x0068, 0x000d},
  50};
  51
  52static u8 *tbl_1280[] = {
  53        (u8[]){
  54                0x0d, 0x80, 0xf1, 0x08, 0x03, 0x04, 0xf1, 0x00,
  55                0x04, 0x05, 0xf1, 0x02, 0x05, 0x00, 0xf1, 0xf1,
  56                0x06, 0x00, 0xf1, 0x0d, 0x20, 0x01, 0xf1, 0x00,
  57                0x21, 0x84, 0xf1, 0x00, 0x0d, 0x00, 0xf1, 0x08,
  58                0xf0, 0x00, 0xf1, 0x01, 0x34, 0x00, 0xf1, 0x00,
  59                0x9b, 0x43, 0xf1, 0x00, 0xa6, 0x05, 0xf1, 0x00,
  60                0xa9, 0x04, 0xf1, 0x00, 0xa1, 0x05, 0xf1, 0x00,
  61                0xa4, 0x04, 0xf1, 0x00, 0xae, 0x0a, 0xf1, 0x08
  62        }, (u8[]){
  63                0xf0, 0x00, 0xf1, 0x02, 0x3a, 0x05, 0xf1, 0xf1,
  64                0x3c, 0x05, 0xf1, 0xf1, 0x59, 0x01, 0xf1, 0x47,
  65                0x5a, 0x01, 0xf1, 0x88, 0x5c, 0x0a, 0xf1, 0x06,
  66                0x5d, 0x0e, 0xf1, 0x0a, 0x64, 0x5e, 0xf1, 0x1c,
  67                0xd2, 0x00, 0xf1, 0xcf, 0xcb, 0x00, 0xf1, 0x01
  68        }, (u8[]){
  69                0xd3, 0x02, 0xd4, 0x28, 0xd5, 0x01, 0xd0, 0x02,
  70                0xd1, 0x18, 0xd2, 0xc1
  71        }
  72};
  73
  74static u8 *tbl_800[] = {
  75        (u8[]){
  76                0x0d, 0x80, 0xf1, 0x08, 0x03, 0x03, 0xf1, 0xc0,
  77                0x04, 0x05, 0xf1, 0x02, 0x05, 0x00, 0xf1, 0xf1,
  78                0x06, 0x00, 0xf1, 0x0d, 0x20, 0x01, 0xf1, 0x00,
  79                0x21, 0x84, 0xf1, 0x00, 0x0d, 0x00, 0xf1, 0x08,
  80                0xf0, 0x00, 0xf1, 0x01, 0x34, 0x00, 0xf1, 0x00,
  81                0x9b, 0x43, 0xf1, 0x00, 0xa6, 0x05, 0xf1, 0x00,
  82                0xa9, 0x03, 0xf1, 0xc0, 0xa1, 0x03, 0xf1, 0x20,
  83                0xa4, 0x02, 0xf1, 0x5a, 0xae, 0x0a, 0xf1, 0x08
  84        }, (u8[]){
  85                0xf0, 0x00, 0xf1, 0x02, 0x3a, 0x05, 0xf1, 0xf1,
  86                0x3c, 0x05, 0xf1, 0xf1, 0x59, 0x01, 0xf1, 0x47,
  87                0x5a, 0x01, 0xf1, 0x88, 0x5c, 0x0a, 0xf1, 0x06,
  88                0x5d, 0x0e, 0xf1, 0x0a, 0x64, 0x5e, 0xf1, 0x1c,
  89                0xd2, 0x00, 0xf1, 0xcf, 0xcb, 0x00, 0xf1, 0x01
  90        }, (u8[]){
  91                0xd3, 0x02, 0xd4, 0x18, 0xd5, 0x21, 0xd0, 0x02,
  92                0xd1, 0x10, 0xd2, 0x59
  93        }
  94};
  95
  96static u8 *tbl_640[] = {
  97        (u8[]){
  98                0x0d, 0x80, 0xf1, 0x08, 0x03, 0x04, 0xf1, 0x04,
  99                0x04, 0x05, 0xf1, 0x02, 0x07, 0x01, 0xf1, 0x7c,
 100                0x08, 0x00, 0xf1, 0x0e, 0x21, 0x80, 0xf1, 0x00,
 101                0x0d, 0x00, 0xf1, 0x08, 0xf0, 0x00, 0xf1, 0x01,
 102                0x34, 0x10, 0xf1, 0x10, 0x3a, 0x43, 0xf1, 0x00,
 103                0xa6, 0x05, 0xf1, 0x02, 0xa9, 0x04, 0xf1, 0x04,
 104                0xa7, 0x02, 0xf1, 0x81, 0xaa, 0x01, 0xf1, 0xe2,
 105                0xae, 0x0c, 0xf1, 0x09
 106        }, (u8[]){
 107                0xf0, 0x00, 0xf1, 0x02, 0x39, 0x03, 0xf1, 0xfc,
 108                0x3b, 0x04, 0xf1, 0x04, 0x57, 0x01, 0xf1, 0xb6,
 109                0x58, 0x02, 0xf1, 0x0d, 0x5c, 0x1f, 0xf1, 0x19,
 110                0x5d, 0x24, 0xf1, 0x1e, 0x64, 0x5e, 0xf1, 0x1c,
 111                0xd2, 0x00, 0xf1, 0x00, 0xcb, 0x00, 0xf1, 0x01
 112        }, (u8[]){
 113                0xd3, 0x02, 0xd4, 0x10, 0xd5, 0x81, 0xd0, 0x02,
 114                0xd1, 0x08, 0xd2, 0xe1
 115        }
 116};
 117
 118static s32 tbl_sat[] = {0x25, 0x1d, 0x15, 0x0d, 0x05, 0x4d, 0x55, 0x5d, 0x2d};
 119static s32 tbl_bright[] = {0, 8, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70};
 120static s32 tbl_backlight[] = {0x0e, 0x06, 0x02};
 121
 122static s32 tbl_cntr1[] = {
 123        0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xe0, 0xf0};
 124static s32 tbl_cntr2[] = {
 125        0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x38, 0x30, 0x20, 0x10};
 126
 127static u8 dat_wbalNL[] =
 128        "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x3b\x04\xf1\x2a\x47\x10\xf1\x10"
 129        "\x9d\x3c\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\x91\xf1\x20"
 130        "\x9c\x91\xf1\x20\x37\x03\xf1\x00" "\x9d\xc5\xf1\x0f\xf0\x00\xf1\x00";
 131
 132static u8 dat_wbalLL[] =
 133        "\xf0\x00\xf1\x01\x05\x00\xf1\x0c" "\x3b\x04\xf1\x2a\x47\x40\xf1\x40"
 134        "\x9d\x20\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\xd1\xf1\x00"
 135        "\x9c\xd1\xf1\x00\x37\x03\xf1\x00" "\x9d\xc5\xf1\x3f\xf0\x00\xf1\x00";
 136
 137static u8 dat_wbalBL[] =
 138        "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x47\x10\xf1\x30\x9d\x3c\xf1\xae"
 139        "\xaf\x10\xf1\x00\xf0\x00\xf1\x02" "\x2f\x91\xf1\x20\x9c\x91\xf1\x20"
 140        "\x37\x03\xf1\x00\x9d\xc5\xf1\x2f" "\xf0\x00\xf1\x00";
 141
 142static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00};
 143
 144static u8 dat_common00[] =
 145        "\x00\x01\x07\x6a\x06\x63\x0d\x6a" "\xc0\x00\x10\x10\xc1\x03\xc2\x42"
 146        "\xd8\x04\x58\x00\x04\x02";
 147static u8 dat_common01[] =
 148        "\x0d\x00\xf1\x0b\x0d\x00\xf1\x08" "\x35\x00\xf1\x22\x68\x00\xf1\x5d"
 149        "\xf0\x00\xf1\x01\x06\x70\xf1\x0e" "\xf0\x00\xf1\x02\xdd\x18\xf1\xe0";
 150static u8 dat_common02[] =
 151        "\x05\x01\xf1\x84\x06\x00\xf1\x44" "\x07\x00\xf1\xbe\x08\x00\xf1\x1e"
 152        "\x20\x01\xf1\x03\x21\x84\xf1\x00" "\x22\x0d\xf1\x0f\x24\x80\xf1\x00"
 153        "\x34\x18\xf1\x2d\x35\x00\xf1\x22" "\x43\x83\xf1\x83\x59\x00\xf1\xff";
 154static u8 dat_common03[] =
 155        "\xf0\x00\xf1\x02\x39\x06\xf1\x8c" "\x3a\x06\xf1\x8c\x3b\x03\xf1\xda"
 156        "\x3c\x05\xf1\x30\x57\x01\xf1\x0c" "\x58\x01\xf1\x42\x59\x01\xf1\x0c"
 157        "\x5a\x01\xf1\x42\x5c\x13\xf1\x0e" "\x5d\x17\xf1\x12\x64\x1e\xf1\x1c";
 158static u8 dat_common04[] =
 159        "\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43";
 160static u8 dat_common05[] =
 161        "\x02\x00\xf1\xee\x03\x29\xf1\x1a" "\x04\x02\xf1\xa4\x09\x00\xf1\x68"
 162        "\x0a\x00\xf1\x2a\x0b\x00\xf1\x04" "\x0c\x00\xf1\x93\x0d\x00\xf1\x82"
 163        "\x0e\x00\xf1\x40\x0f\x00\xf1\x5f" "\x10\x00\xf1\x4e\x11\x00\xf1\x5b";
 164static u8 dat_common06[] =
 165        "\x15\x00\xf1\xc9\x16\x00\xf1\x5e" "\x17\x00\xf1\x9d\x18\x00\xf1\x06"
 166        "\x19\x00\xf1\x89\x1a\x00\xf1\x12" "\x1b\x00\xf1\xa1\x1c\x00\xf1\xe4"
 167        "\x1d\x00\xf1\x7a\x1e\x00\xf1\x64" "\xf6\x00\xf1\x5f";
 168static u8 dat_common07[] =
 169        "\xf0\x00\xf1\x01\x53\x09\xf1\x03" "\x54\x3d\xf1\x1c\x55\x99\xf1\x72"
 170        "\x56\xc1\xf1\xb1\x57\xd8\xf1\xce" "\x58\xe0\xf1\x00\xdc\x0a\xf1\x03"
 171        "\xdd\x45\xf1\x20\xde\xae\xf1\x82" "\xdf\xdc\xf1\xc9\xe0\xf6\xf1\xea"
 172        "\xe1\xff\xf1\x00";
 173static u8 dat_common08[] =
 174        "\xf0\x00\xf1\x01\x80\x00\xf1\x06" "\x81\xf6\xf1\x08\x82\xfb\xf1\xf7"
 175        "\x83\x00\xf1\xfe\xb6\x07\xf1\x03" "\xb7\x18\xf1\x0c\x84\xfb\xf1\x06"
 176        "\x85\xfb\xf1\xf9\x86\x00\xf1\xff" "\xb8\x07\xf1\x04\xb9\x16\xf1\x0a";
 177static u8 dat_common09[] =
 178        "\x87\xfa\xf1\x05\x88\xfc\xf1\xf9" "\x89\x00\xf1\xff\xba\x06\xf1\x03"
 179        "\xbb\x17\xf1\x09\x8a\xe8\xf1\x14" "\x8b\xf7\xf1\xf0\x8c\xfd\xf1\xfa"
 180        "\x8d\x00\xf1\x00\xbc\x05\xf1\x01" "\xbd\x0c\xf1\x08\xbe\x00\xf1\x14";
 181static u8 dat_common10[] =
 182        "\x8e\xea\xf1\x13\x8f\xf7\xf1\xf2" "\x90\xfd\xf1\xfa\x91\x00\xf1\x00"
 183        "\xbf\x05\xf1\x01\xc0\x0a\xf1\x08" "\xc1\x00\xf1\x0c\x92\xed\xf1\x0f"
 184        "\x93\xf9\xf1\xf4\x94\xfe\xf1\xfb" "\x95\x00\xf1\x00\xc2\x04\xf1\x01"
 185        "\xc3\x0a\xf1\x07\xc4\x00\xf1\x10";
 186static u8 dat_common11[] =
 187        "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x25\x00\xf1\x55\x34\x10\xf1\x10"
 188        "\x35\xf0\xf1\x10\x3a\x02\xf1\x03" "\x3b\x04\xf1\x2a\x9b\x43\xf1\x00"
 189        "\xa4\x03\xf1\xc0\xa7\x02\xf1\x81";
 190
 191static int  mi1320_init_at_startup(struct gspca_dev *gspca_dev);
 192static int  mi1320_configure_alt(struct gspca_dev *gspca_dev);
 193static int  mi1320_init_pre_alt(struct gspca_dev *gspca_dev);
 194static int  mi1320_init_post_alt(struct gspca_dev *gspca_dev);
 195static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev);
 196static int  mi1320_sensor_settings(struct gspca_dev *gspca_dev);
 197static int  mi1320_camera_settings(struct gspca_dev *gspca_dev);
 198/*==========================================================================*/
 199
 200void mi1320_init_settings(struct gspca_dev *gspca_dev)
 201{
 202        struct sd *sd = (struct sd *) gspca_dev;
 203
 204        sd->vcur.backlight  =  0;
 205        sd->vcur.brightness =  0;
 206        sd->vcur.sharpness  =  6;
 207        sd->vcur.contrast   = 10;
 208        sd->vcur.gamma      = 20;
 209        sd->vcur.hue        =  0;
 210        sd->vcur.saturation =  6;
 211        sd->vcur.whitebal   =  0;
 212        sd->vcur.mirror     = 0;
 213        sd->vcur.flip       = 0;
 214        sd->vcur.AC50Hz     = 1;
 215
 216        sd->vmax.backlight  =  2;
 217        sd->vmax.brightness =  8;
 218        sd->vmax.sharpness  =  7;
 219        sd->vmax.contrast   =  0; /* 10 but not working with this driver */
 220        sd->vmax.gamma      = 40;
 221        sd->vmax.hue        =  5 + 1;
 222        sd->vmax.saturation =  8;
 223        sd->vmax.whitebal   =  2;
 224        sd->vmax.mirror     = 1;
 225        sd->vmax.flip       = 1;
 226        sd->vmax.AC50Hz     = 1;
 227
 228        sd->dev_camera_settings = mi1320_camera_settings;
 229        sd->dev_init_at_startup = mi1320_init_at_startup;
 230        sd->dev_configure_alt   = mi1320_configure_alt;
 231        sd->dev_init_pre_alt    = mi1320_init_pre_alt;
 232        sd->dev_post_unset_alt  = mi1320_post_unset_alt;
 233}
 234
 235/*==========================================================================*/
 236
 237static void common(struct gspca_dev *gspca_dev)
 238{
 239        s32 n; /* reserved for FETCH functions */
 240
 241        ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 22, dat_common00);
 242        ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL);
 243        ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 32, dat_common01);
 244        n = fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common));
 245        ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common02);
 246        ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common03);
 247        ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 16, dat_common04);
 248        ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common05);
 249        ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 44, dat_common06);
 250        keep_on_fetching_validx(gspca_dev, tbl_common,
 251                                        ARRAY_SIZE(tbl_common), n);
 252        ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 52, dat_common07);
 253        ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common08);
 254        ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common09);
 255        ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 56, dat_common10);
 256        keep_on_fetching_validx(gspca_dev, tbl_common,
 257                                        ARRAY_SIZE(tbl_common), n);
 258        ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, dat_common11);
 259        keep_on_fetching_validx(gspca_dev, tbl_common,
 260                                        ARRAY_SIZE(tbl_common), n);
 261}
 262
 263static int mi1320_init_at_startup(struct gspca_dev *gspca_dev)
 264{
 265        fetch_validx(gspca_dev, tbl_init_at_startup,
 266                                ARRAY_SIZE(tbl_init_at_startup));
 267
 268        common(gspca_dev);
 269
 270/*      ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */
 271
 272        return 0;
 273}
 274
 275static int mi1320_init_pre_alt(struct gspca_dev *gspca_dev)
 276{
 277        struct sd *sd = (struct sd *) gspca_dev;
 278
 279        sd->mirrorMask = 0;
 280
 281        sd->vold.backlight  = -1;
 282        sd->vold.brightness = -1;
 283        sd->vold.sharpness  = -1;
 284        sd->vold.contrast   = -1;
 285        sd->vold.saturation = -1;
 286        sd->vold.gamma    = -1;
 287        sd->vold.hue      = -1;
 288        sd->vold.whitebal = -1;
 289        sd->vold.mirror   = -1;
 290        sd->vold.flip     = -1;
 291        sd->vold.AC50Hz   = -1;
 292
 293        common(gspca_dev);
 294
 295        mi1320_sensor_settings(gspca_dev);
 296
 297        mi1320_init_post_alt(gspca_dev);
 298
 299        return 0;
 300}
 301
 302static int mi1320_init_post_alt(struct gspca_dev *gspca_dev)
 303{
 304        mi1320_camera_settings(gspca_dev);
 305
 306        return 0;
 307}
 308
 309static int mi1320_sensor_settings(struct gspca_dev *gspca_dev)
 310{
 311        s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
 312
 313        ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
 314
 315        fetch_validx(gspca_dev, tbl_sensor_settings_common,
 316                                ARRAY_SIZE(tbl_sensor_settings_common));
 317
 318        switch (reso) {
 319        case IMAGE_1280:
 320                fetch_validx(gspca_dev, tbl_sensor_settings_1280,
 321                                        ARRAY_SIZE(tbl_sensor_settings_1280));
 322                ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_1280[0]);
 323                ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_1280[1]);
 324                ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_1280[2]);
 325                break;
 326
 327        case IMAGE_800:
 328                fetch_validx(gspca_dev, tbl_sensor_settings_800,
 329                                        ARRAY_SIZE(tbl_sensor_settings_800));
 330                ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_800[0]);
 331                ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_800[1]);
 332                ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_800[2]);
 333                break;
 334
 335        default:
 336                fetch_validx(gspca_dev, tbl_sensor_settings_640,
 337                                        ARRAY_SIZE(tbl_sensor_settings_640));
 338                ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 60, tbl_640[0]);
 339                ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_640[1]);
 340                ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_640[2]);
 341                break;
 342        }
 343        return 0;
 344}
 345
 346static int mi1320_configure_alt(struct gspca_dev *gspca_dev)
 347{
 348        s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
 349
 350        switch (reso) {
 351        case IMAGE_640:
 352                gspca_dev->alt = 3 + 1;
 353                break;
 354
 355        case IMAGE_800:
 356        case IMAGE_1280:
 357                gspca_dev->alt = 1 + 1;
 358                break;
 359        }
 360        return 0;
 361}
 362
 363static int mi1320_camera_settings(struct gspca_dev *gspca_dev)
 364{
 365        struct sd *sd = (struct sd *) gspca_dev;
 366
 367        s32 backlight = sd->vcur.backlight;
 368        s32 bright = sd->vcur.brightness;
 369        s32 sharp  = sd->vcur.sharpness;
 370        s32 cntr   = sd->vcur.contrast;
 371        s32 gam    = sd->vcur.gamma;
 372        s32 hue    = sd->vcur.hue;
 373        s32 sat    = sd->vcur.saturation;
 374        s32 wbal   = sd->vcur.whitebal;
 375        s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
 376        s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
 377        s32 freq   = (sd->vcur.AC50Hz > 0);
 378        s32 i;
 379
 380        if (freq != sd->vold.AC50Hz) {
 381                sd->vold.AC50Hz = freq;
 382
 383                freq = 2 * (freq == 0);
 384                ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
 385                ctrl_out(gspca_dev, 0x40, 1, 0xba02, 0x00f1, 0, NULL);
 386                ctrl_out(gspca_dev, 0x40, 1, 0xba00       , 0x005b, 0, NULL);
 387                ctrl_out(gspca_dev, 0x40, 1, 0xba01 + freq, 0x00f1, 0, NULL);
 388        }
 389
 390        if (wbal != sd->vold.whitebal) {
 391                sd->vold.whitebal = wbal;
 392                if (wbal < 0 || wbal > sd->vmax.whitebal)
 393                        wbal = 0;
 394
 395                for (i = 0; i < 2; i++) {
 396                        if (wbal == 0) { /* Normal light */
 397                                ctrl_out(gspca_dev, 0x40, 1,
 398                                                0x0010, 0x0010, 0, NULL);
 399                                ctrl_out(gspca_dev, 0x40, 1,
 400                                                0x0003, 0x00c1, 0, NULL);
 401                                ctrl_out(gspca_dev, 0x40, 1,
 402                                                0x0042, 0x00c2, 0, NULL);
 403                                ctrl_out(gspca_dev, 0x40, 3,
 404                                                0xba00, 0x0200, 48, dat_wbalNL);
 405                        }
 406
 407                        if (wbal == 1) { /* Low light */
 408                                ctrl_out(gspca_dev, 0x40, 1,
 409                                                0x0010, 0x0010, 0, NULL);
 410                                ctrl_out(gspca_dev, 0x40, 1,
 411                                                0x0004, 0x00c1, 0, NULL);
 412                                ctrl_out(gspca_dev, 0x40, 1,
 413                                                0x0043, 0x00c2, 0, NULL);
 414                                ctrl_out(gspca_dev, 0x40, 3,
 415                                                0xba00, 0x0200, 48, dat_wbalLL);
 416                        }
 417
 418                        if (wbal == 2) { /* Back light */
 419                                ctrl_out(gspca_dev, 0x40, 1,
 420                                                0x0010, 0x0010, 0, NULL);
 421                                ctrl_out(gspca_dev, 0x40, 1,
 422                                                0x0003, 0x00c1, 0, NULL);
 423                                ctrl_out(gspca_dev, 0x40, 1,
 424                                                0x0042, 0x00c2, 0, NULL);
 425                                ctrl_out(gspca_dev, 0x40, 3,
 426                                                0xba00, 0x0200, 44, dat_wbalBL);
 427                        }
 428                }
 429        }
 430
 431        if (bright != sd->vold.brightness) {
 432                sd->vold.brightness = bright;
 433                if (bright < 0 || bright > sd->vmax.brightness)
 434                        bright = 0;
 435
 436                bright = tbl_bright[bright];
 437                ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
 438                ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
 439                ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x0034, 0, NULL);
 440                ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x00f1, 0, NULL);
 441        }
 442
 443        if (sat != sd->vold.saturation) {
 444                sd->vold.saturation = sat;
 445                if (sat < 0 || sat > sd->vmax.saturation)
 446                        sat = 0;
 447
 448                sat = tbl_sat[sat];
 449                ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
 450                ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
 451                ctrl_out(gspca_dev, 0x40, 1, 0xba00      , 0x0025, 0, NULL);
 452                ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sat, 0x00f1, 0, NULL);
 453        }
 454
 455        if (sharp != sd->vold.sharpness) {
 456                sd->vold.sharpness = sharp;
 457                if (sharp < 0 || sharp > sd->vmax.sharpness)
 458                        sharp = 0;
 459
 460                ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
 461                ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
 462                ctrl_out(gspca_dev, 0x40, 1, 0xba00        , 0x0005, 0, NULL);
 463                ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sharp, 0x00f1, 0, NULL);
 464        }
 465
 466        if (hue != sd->vold.hue) {
 467                /* 0=normal  1=NB  2="sepia"  3=negative  4=other  5=other2 */
 468                if (hue < 0 || hue > sd->vmax.hue)
 469                        hue = 0;
 470                if (hue == sd->vmax.hue)
 471                        sd->swapRB = 1;
 472                else
 473                        sd->swapRB = 0;
 474
 475                ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
 476                ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
 477                ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
 478                ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
 479                                                        0, NULL);
 480        }
 481
 482        if (backlight != sd->vold.backlight) {
 483                sd->vold.backlight = backlight;
 484                if (backlight < 0 || backlight > sd->vmax.backlight)
 485                        backlight = 0;
 486
 487                backlight = tbl_backlight[backlight];
 488                for (i = 0; i < 2; i++) {
 489                        ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
 490                        ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
 491                        ctrl_out(gspca_dev, 0x40, 1, 0xba74, 0x0006, 0, NULL);
 492                        ctrl_out(gspca_dev, 0x40, 1, 0xba80 + backlight, 0x00f1,
 493                                                                0, NULL);
 494                }
 495        }
 496
 497        if (hue != sd->vold.hue) {
 498                sd->vold.hue = hue;
 499
 500                ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
 501                ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
 502                ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
 503                ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
 504                                                        0, NULL);
 505        }
 506
 507        if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
 508                u8 dat_hvflip2[4] = {0x20, 0x01, 0xf1, 0x00};
 509                sd->vold.mirror = mirror;
 510                sd->vold.flip = flip;
 511
 512                dat_hvflip2[3] = flip + 2 * mirror;
 513                ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip1);
 514                ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip2);
 515        }
 516
 517        if (gam != sd->vold.gamma) {
 518                sd->vold.gamma = gam;
 519                if (gam < 0 || gam > sd->vmax.gamma)
 520                        gam = 0;
 521
 522                gam = 2 * gam;
 523                ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
 524                ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
 525                ctrl_out(gspca_dev, 0x40, 1, 0xba04      , 0x003b, 0, NULL);
 526                ctrl_out(gspca_dev, 0x40, 1, 0xba02 + gam, 0x00f1, 0, NULL);
 527        }
 528
 529        if (cntr != sd->vold.contrast) {
 530                sd->vold.contrast = cntr;
 531                if (cntr < 0 || cntr > sd->vmax.contrast)
 532                        cntr = 0;
 533
 534                ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
 535                ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
 536                ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr1[cntr], 0x0035,
 537                                                        0, NULL);
 538                ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr2[cntr], 0x00f1,
 539                                                        0, NULL);
 540        }
 541
 542        return 0;
 543}
 544
 545static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev)
 546{
 547        ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
 548
 549        fetch_validx(gspca_dev, tbl_post_unset_alt,
 550                                ARRAY_SIZE(tbl_post_unset_alt));
 551}
 552