/* This function is used to monitor webcam orientation */
static void sd_callback(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;

	if (!_OV9655_) {
		u8 state;
		u8 upsideDown;

		/* Probe sensor orientation */
		ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, (void *)&state);

		/* C8/40 means upside-down (looking backwards) */
		/* D8/50 means right-up (looking onwards) */
		upsideDown = (state == 0xc8 || state == 0x40);

		if (upsideDown && sd->nbRightUp > -4) {
			if (sd->nbRightUp > 0)
				sd->nbRightUp = 0;
			if (sd->nbRightUp == -3) {
				sd->mirrorMask = 1;
				sd->waitSet = 1;
			}
			sd->nbRightUp--;
		}
		if (!upsideDown && sd->nbRightUp < 4) {
			if (sd->nbRightUp  < 0)
				sd->nbRightUp = 0;
			if (sd->nbRightUp == 3) {
				sd->mirrorMask = 0;
				sd->waitSet = 1;
			}
			sd->nbRightUp++;
		}
	}

	if (sd->waitSet)
		sd->dev_camera_settings(gspca_dev);
}
Beispiel #2
0
static void sd_callback(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;

	if (!_OV9655_) {
		u8 state;
		u8 upsideDown;

		
		ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, (void *)&state);

		
		
		upsideDown = (state == 0xc8 || state == 0x40);

		if (upsideDown && sd->nbRightUp > -4) {
			if (sd->nbRightUp > 0)
				sd->nbRightUp = 0;
			if (sd->nbRightUp == -3) {
				sd->mirrorMask = 1;
				sd->waitSet = 1;
			}
			sd->nbRightUp--;
		}
		if (!upsideDown && sd->nbRightUp < 4) {
			if (sd->nbRightUp  < 0)
				sd->nbRightUp = 0;
			if (sd->nbRightUp == 3) {
				sd->mirrorMask = 0;
				sd->waitSet = 1;
			}
			sd->nbRightUp++;
		}
	}

	if (sd->waitSet)
		sd->dev_camera_settings(gspca_dev);
}
Beispiel #3
0
static int ov9655_init_post_alt(struct gspca_dev *gspca_dev)
{
	s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
	s32 n; 
	s32 i;
	u8 **tbl;

	ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);

	tbl = (reso == IMAGE_640) ? tbl_640 : tbl_800;

	ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
			tbl_length[0], tbl[0]);
	for (i = 1; i < 7; i++)
		ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200,
				tbl_length[i], tbl[i]);
	ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
			tbl_length[7], tbl[7]);

	n = fetch_validx(gspca_dev, tbl_init_post_alt,
			ARRAY_SIZE(tbl_init_post_alt));

	ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);
	ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);
	ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);
	ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);
	ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_1);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);

	ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);
	ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);
	ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);
	ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);
	ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_1);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);

	ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);
	ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
	keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
					ARRAY_SIZE(tbl_init_post_alt), n);

	ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_1);

	ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post_2);
	ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_3);

	ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post_4);
	ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_5);

	ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post_6);
	ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_7);

	ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post_8);

	ov9655_camera_settings(gspca_dev);

	return 0;
}
static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
				u16 vendor_id, u16 product_id)
{
	struct sd *sd = (struct sd *) gspca_dev;
	u8 probe, nb26, nb96, nOV, ntry;

	if (product_id == 0xf191)
		sd->sensor = ID_MI1320;

	if (sd->sensor == 0xff) {
		ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
		ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);

		ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x0000, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x00c0, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c1, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c2, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x0020, 0x0006, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL);
		msleep(56);

		PDEBUG(D_PROBE, "probing for sensor MI2020 or OVXXXX");
		nOV = 0;
		for (ntry = 0; ntry < 4; ntry++) {
			ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
			msleep(3);
			ctrl_out(gspca_dev, 0x40, 1, 0x0063, 0x0006, 0, NULL);
			msleep(3);
			ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL);
			msleep(10);
			ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe);
			PDEBUG(D_PROBE, "probe=0x%02x", probe);
			if (probe == 0xff)
				nOV++;
		}

		if (nOV) {
			PDEBUG(D_PROBE, "0xff -> OVXXXX");
			PDEBUG(D_PROBE, "probing for sensor OV2640 or OV9655");

			nb26 = nb96 = 0;
			for (ntry = 0; ntry < 4; ntry++) {
				ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000,
						0, NULL);
				msleep(3);
				ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a,
						0, NULL);
				msleep(10);

				/* Wait for 26(OV2640) or 96(OV9655) */
				ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a,
						1, &probe);

				if (probe == 0x26 || probe == 0x40) {
					PDEBUG(D_PROBE,
						"probe=0x%02x -> OV2640",
						probe);
					sd->sensor = ID_OV2640;
					nb26 += 4;
					break;
				}
				if (probe == 0x96 || probe == 0x55) {
					PDEBUG(D_PROBE,
						"probe=0x%02x -> OV9655",
						probe);
					sd->sensor = ID_OV9655;
					nb96 += 4;
					break;
				}
				PDEBUG(D_PROBE, "probe=0x%02x", probe);
				if (probe == 0x00)
					nb26++;
				if (probe == 0xff)
					nb96++;
				msleep(3);
			}
			if (nb26 < 4 && nb96 < 4)
				return -1;
		} else {
			PDEBUG(D_PROBE, "Not any 0xff -> MI2020");
			sd->sensor = ID_MI2020;
		}
	}

	if (_MI1320_) {
		PDEBUG(D_PROBE, "05e3:f191 sensor MI1320 (1.3M)");
	} else if (_MI2020_) {
		PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 (2.0M)");
	} else if (_MI2020b_) {
		PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 alt. driver (2.0M)");
	} else if (_OV9655_) {
		PDEBUG(D_PROBE, "05e3:0503 sensor OV9655 (1.3M)");
	} else if (_OV2640_) {
		PDEBUG(D_PROBE, "05e3:0503 sensor OV2640 (2.0M)");
	} else {
		PDEBUG(D_PROBE, "***** Unknown sensor *****");
		return -1;
	}

	return 0;
}
Beispiel #5
0
static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
				s32 vendor_id, s32 product_id)
{
	struct sd *sd = (struct sd *) gspca_dev;
	u8 probe, nb26, nb96, nOV, ntry;

	if (product_id == 0xf191)
		sd->sensor = ID_MI1320;

	if (sd->sensor == 0xff) {
		ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
		ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);

		ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x0000, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x00c0, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c1, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c2, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x0020, 0x0006, 0, NULL);
		msleep(3);
		ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL);
		msleep(56);

		nOV = 0;
		for (ntry = 0; ntry < 4; ntry++) {
			ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
			msleep(3);
			ctrl_out(gspca_dev, 0x40, 1, 0x0063, 0x0006, 0, NULL);
			msleep(3);
			ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL);
			msleep(10);
			ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe);
			PDEBUG(D_PROBE, "1st probe=%02x", probe);
			if (probe == 0xff)
				nOV++;
		}

		if (nOV) {
			PDEBUG(D_PROBE, "0xff -> sensor OVXXXX");
			PDEBUG(D_PROBE, "Probing for sensor OV2640 or OV9655");

			nb26 = nb96 = 0;
			for (ntry = 0; ntry < 4; ntry++) {
				ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000,
						0, NULL);
				msleep(3);
				ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a,
						0, NULL);
				msleep(10);
				
				ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a,
						1, &probe);

				PDEBUG(D_PROBE, "2nd probe=%02x", probe);
				if (probe == 0x00)
					nb26++;
				if (probe == 0x26 || probe == 0x40) {
					sd->sensor = ID_OV2640;
					nb26 += 4;
					break;
				}
				if (probe == 0x96 || probe == 0x55) {
					sd->sensor = ID_OV9655;
					nb96 += 4;
					break;
				}
				if (probe == 0xff)
					nb96++;
				msleep(3);
			}
			if (nb26 < 4 && nb96 < 4) {
				PDEBUG(D_PROBE, "No relevant answer ");
				PDEBUG(D_PROBE, "* 1.3Mpixels -> use OV9655");
				PDEBUG(D_PROBE, "* 2.0Mpixels -> use OV2640");
				PDEBUG(D_PROBE,
					"To force a sensor, add that line to "
					"/etc/modprobe.d/options.conf:");
				PDEBUG(D_PROBE, "options gspca_gl860 "
					"sensor=\"OV2640\" or \"OV9655\"");
				return -1;
			}
		} else { 
			PDEBUG(D_PROBE, "No 0xff -> sensor MI2020");
			sd->sensor = ID_MI2020;
		}
	}

	if (_MI1320_) {
		PDEBUG(D_PROBE, "05e3:f191 sensor MI1320 (1.3M)");
	} else if (_MI2020_) {
		PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 (2.0M)");
	} else if (_MI2020b_) {
		PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 alt. driver (2.0M)");
	} else if (_OV9655_) {
		PDEBUG(D_PROBE, "05e3:0503 sensor OV9655 (1.3M)");
	} else if (_OV2640_) {
		PDEBUG(D_PROBE, "05e3:0503 sensor OV2640 (2.0M)");
	} else {
		PDEBUG(D_PROBE, "***** Unknown sensor *****");
		return -1;
	}

	return 0;
}
Beispiel #6
0
static int ov2640_camera_settings(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;

	s32 backlight = sd->vcur.backlight;
	s32 bright = sd->vcur.brightness;
	s32 sharp  = sd->vcur.sharpness;
	s32 gam    = sd->vcur.gamma;
	s32 cntr   = sd->vcur.contrast;
	s32 sat    = sd->vcur.saturation;
	s32 hue    = sd->vcur.hue;
	s32 wbal   = sd->vcur.whitebal;
	s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) == 0);
	s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) == 0);

	if (backlight != sd->vold.backlight) {
		/* No sd->vold.backlight=backlight; (to be done again later) */
		if (backlight < 0 || backlight > sd->vmax.backlight)
			backlight = 0;

		ctrl_out(gspca_dev, 0x40, 1, 0x6001                 , 0x00ff,
				0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight     , 0x0024,
				0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025,
				0, NULL);
	}

	if (bright != sd->vold.brightness) {
		sd->vold.brightness = bright;
		if (bright < 0 || bright > sd->vmax.brightness)
			bright = 0;

		ctrl_out(gspca_dev, 0x40, 1, 0x6000         , 0x00ff, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6009         , 0x007c, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6000 + bright, 0x007d, 0, NULL);
	}

	if (wbal != sd->vold.whitebal) {
		sd->vold.whitebal = wbal;
		if (wbal < 0 || wbal > sd->vmax.whitebal)
			wbal = 0;

		ctrl_out(gspca_dev, 0x40, 1, 0x6000       , 0x00ff, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6003       , 0x007c, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6000 + wbal, 0x007d, 0, NULL);
	}

	if (cntr != sd->vold.contrast) {
		sd->vold.contrast = cntr;
		if (cntr < 0 || cntr > sd->vmax.contrast)
			cntr = 0;

		ctrl_out(gspca_dev, 0x40, 1, 0x6000       , 0x00ff, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6007       , 0x007c, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6000 + cntr, 0x007d, 0, NULL);
	}

	if (sat != sd->vold.saturation) {
		sd->vold.saturation = sat;
		if (sat < 0 || sat > sd->vmax.saturation)
			sat = 0;

		ctrl_out(gspca_dev, 0x40, 1, 0x6000      , 0x00ff, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6001      , 0x007c, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6000 + sat, 0x007d, 0, NULL);
	}

	if (sharp != sd->vold.sharpness) {
		sd->vold.sharpness = sharp;
		if (sharp < 0 || sharp > sd->vmax.sharpness)
			sharp = 0;

		ctrl_out(gspca_dev, 0x40, 1, 0x6000        , 0x00ff, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6001        , 0x0092, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x60c0 + sharp, 0x0093, 0, NULL);
	}

	if (hue != sd->vold.hue) {
		sd->vold.hue = hue;
		if (hue < 0 || hue > sd->vmax.hue)
			hue = 0;

		ctrl_out(gspca_dev, 0x40, 1, 0x6000     , 0x00ff, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6002     , 0x007c, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6000 + hue * (hue < 255), 0x007d,
				0, NULL);
		if (hue >= 255)
			sd->swapRB = 1;
		else
			sd->swapRB = 0;
	}

	if (gam != sd->vold.gamma) {
		sd->vold.gamma = gam;
		if (gam < 0 || gam > sd->vmax.gamma)
			gam = 0;

		ctrl_out(gspca_dev, 0x40, 1, 0x6000      , 0x00ff, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6008      , 0x007c, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6000 + gam, 0x007d, 0, NULL);
	}

	if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
		sd->vold.mirror = mirror;
		sd->vold.flip   = flip;

		mirror = 0x80 * mirror;
		ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL);
		ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28);
		ctrl_out(gspca_dev, 0x40, 1, 0x6028 + mirror, 0x0004, 0, NULL);

		flip = 0x50 * flip + mirror;
		ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL);
		ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8);
		ctrl_out(gspca_dev, 0x40, 1, 0x6028 + flip, 0x0004, 0, NULL);

		ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50);
	}

	if (backlight != sd->vold.backlight) {
		sd->vold.backlight = backlight;

		ctrl_out(gspca_dev, 0x40, 1, 0x6001                 , 0x00ff,
				0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight     , 0x0024,
				0, NULL);
		ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025,
				0, NULL);
	}

	return 0;
}
Beispiel #7
0
static int mi2020_init_post_alt(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
	s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;

	s32 backlight = sd->vcur.backlight;
	s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
	s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
	s32 freq   = (sd->vcur.AC50Hz  > 0);

	u8 dat_freq2[] = {0x90, 0x00, 0x80};
	u8 dat_multi1[] = {0x8c, 0xa7, 0x00};
	u8 dat_multi2[] = {0x90, 0x00, 0x00};
	u8 dat_multi3[] = {0x8c, 0xa7, 0x00};
	u8 dat_multi4[] = {0x90, 0x00, 0x00};
	u8 dat_hvflip2[] = {0x90, 0x04, 0x6c};
	u8 dat_hvflip4[] = {0x90, 0x00, 0x24};
	u8 c;

	sd->nbIm = -1;

	dat_freq2[2] = freq ? 0xc0 : 0x80;
	dat_multi1[2] = 0x9d;
	dat_multi3[2] = dat_multi1[2] + 1;
	dat_multi4[2] = dat_multi2[2] = backlight;
	dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror);
	dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror);

	msleep(200);

	ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
	msleep(3); 

	common(gspca_dev);

	ctrl_out(gspca_dev, 0x40,  1, 0x0041, 0x0000,  0, NULL);
	msleep(70);

	if (_MI2020b_)
		ctrl_out(gspca_dev, 0x40,  1, 0x0040, 0x0000,  0, NULL);

	ctrl_out(gspca_dev, 0x40,  1, 0x0010, 0x0010,  0, NULL);
	ctrl_out(gspca_dev, 0x40,  1, 0x0003, 0x00c1,  0, NULL);
	ctrl_out(gspca_dev, 0x40,  1, 0x0042, 0x00c2,  0, NULL);
	ctrl_out(gspca_dev, 0x40,  1, 0x006a, 0x000d,  0, NULL);

	switch (reso) {
	case IMAGE_640:
	case IMAGE_800:
		if (reso != IMAGE_800)
			ctrl_out(gspca_dev, 0x40,  3, 0x0000, 0x0200,
				12, dat_640);
		else
			ctrl_out(gspca_dev, 0x40,  3, 0x0000, 0x0200,
				12, dat_800);

		if (_MI2020c_)
			fetch_idxdata(gspca_dev, tbl_init_post_alt_low_a,
					ARRAY_SIZE(tbl_init_post_alt_low_a));

		if (reso == IMAGE_800)
			fetch_idxdata(gspca_dev, tbl_init_post_alt_low_b,
					ARRAY_SIZE(tbl_init_post_alt_low_b));

		fetch_idxdata(gspca_dev, tbl_init_post_alt_low_c,
				ARRAY_SIZE(tbl_init_post_alt_low_c));

		if (_MI2020b_) {
			ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
			ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
			ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
			msleep(150);
		} else if (_MI2020c_) {
			ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
			ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
			ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
			msleep(120);
			ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
			msleep(30);
		} else if (_MI2020_) {
			ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
			ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
			ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
			msleep(120);
			ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
			msleep(30);
		}

		
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
		msleep(20);
		
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
		
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa2\x0c");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x17");
		
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
		msleep(5);

		if (_MI2020c_) {
			fetch_idxdata(gspca_dev, tbl_init_post_alt_low_d,
					ARRAY_SIZE(tbl_init_post_alt_low_d));
		} else {
			ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c);
			msleep(14); 

			
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_hvflip1);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_hvflip2);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_hvflip3);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_hvflip4);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_hvflip5);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_hvflip6);
			msleep(21);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_dummy1);
			msleep(5);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_dummy1);
			msleep(5);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_dummy1);
			msleep(5);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_dummy1);
			msleep(5);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_dummy1);
			msleep(5);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, dat_dummy1);
			
			msleep(246); 

			sd->nbIm = 0;
		}
		break;

	case IMAGE_1280:
	case IMAGE_1600:
		if (reso == IMAGE_1280) {
			ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
					12, dat_1280);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, "\x8c\x27\x07");
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, "\x90\x05\x04");
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, "\x8c\x27\x09");
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, "\x90\x04\x02");
		} else {
			ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
					12, dat_1600);
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, "\x8c\x27\x07");
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, "\x90\x06\x40");
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, "\x8c\x27\x09");
			ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
					3, "\x90\x04\xb0");
		}

		fetch_idxdata(gspca_dev, tbl_init_post_alt_big_a,
				ARRAY_SIZE(tbl_init_post_alt_big_a));

		if (reso == IMAGE_1600)
			msleep(13); 
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\x27\x97");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x01\x00");
		msleep(53);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01");
		if (reso == IMAGE_1600)
			msleep(13); 
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00");
		msleep(53);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x72");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x02");
		if (reso == IMAGE_1600)
			msleep(13); 
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01");
		msleep(53);

		if (_MI2020b_) {
			ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
			if (reso == IMAGE_1600)
				msleep(500); 
			ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
			ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
			msleep(1850);
		} else if (_MI2020c_ || _MI2020_) {
			ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
			ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
			ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
			msleep(1850);
			ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
			msleep(30);
		}

		
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
		msleep(20);
		
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
		
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa2\x0c");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x17");
		
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
		msleep(6); 

		ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c);
		msleep(14);

		if (_MI2020c_)
			fetch_idxdata(gspca_dev, tbl_init_post_alt_big_b,
					ARRAY_SIZE(tbl_init_post_alt_big_b));

		
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6);
		
		msleep(16);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00");
		if (reso == IMAGE_1600)
			msleep(25); 
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x00");
		msleep(103);
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x03");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x02");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa1\x20");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x72");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x8c\xa7\x02");
		ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, "\x90\x00\x01");
		sd->nbIm = 0;

		if (_MI2020c_)
			fetch_idxdata(gspca_dev, tbl_init_post_alt_big_c,
					ARRAY_SIZE(tbl_init_post_alt_big_c));
	}

	sd->vold.mirror    = mirror;
	sd->vold.flip      = flip;
	sd->vold.AC50Hz    = freq;
	sd->vold.backlight = backlight;

	mi2020_camera_settings(gspca_dev);

	return 0;
}