static int sd_start()

in usb/gspca/sonixj.c [2170:2483]


static int sd_start(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
	int i;
	u8 reg01, reg17;
	u8 reg0102[2];
	const u8 *sn9c1xx;
	const u8 (*init)[8];
	const u8 *reg9a;
	int mode;
	static const u8 reg9a_def[] =
		{0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
	static const u8 reg9a_spec[] =
		{0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
	static const u8 regd4[] = {0x60, 0x00, 0x00};
	static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
	static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
	static const u8 CA_adcm1700[] =
				{ 0x14, 0xec, 0x0a, 0xf6 };
	static const u8 CA_po2030n[] =
				{ 0x1e, 0xe2, 0x14, 0xec };
	static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };	/* MI0360 */
	static const u8 CE_gc0307[] =
				{ 0x32, 0xce, 0x2d, 0xd3 };
	static const u8 CE_ov76xx[] =
				{ 0x32, 0xdd, 0x32, 0xdd };
	static const u8 CE_po2030n[] =
				{ 0x14, 0xe7, 0x1e, 0xdd };

	/* create the JPEG header */
	jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
			gspca_dev->pixfmt.width,
			0x21);		/* JPEG 422 */

	/* initialize the bridge */
	sn9c1xx = sn_tb[sd->sensor];

	/* sensor clock already enabled in sd_init */
	/* reg_w1(gspca_dev, 0xf1, 0x00); */
	reg01 = sn9c1xx[1];
	if (sd->flags & F_PDN_INV)
		reg01 ^= S_PDN_INV;		/* power down inverted */
	reg_w1(gspca_dev, 0x01, reg01);

	/* configure gpio */
	reg0102[0] = reg01;
	reg0102[1] = sn9c1xx[2];
	if (gspca_dev->audio)
		reg0102[1] |= 0x04;	/* keep the audio connection */
	reg_w(gspca_dev, 0x01, reg0102, 2);
	reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
	reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
	switch (sd->sensor) {
	case SENSOR_GC0307:
	case SENSOR_OV7660:
	case SENSOR_PO1030:
	case SENSOR_PO2030N:
	case SENSOR_SOI768:
	case SENSOR_SP80708:
		reg9a = reg9a_spec;
		break;
	default:
		reg9a = reg9a_def;
		break;
	}
	reg_w(gspca_dev, 0x9a, reg9a, 6);

	reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);

	reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);

	reg17 = sn9c1xx[0x17];
	switch (sd->sensor) {
	case SENSOR_GC0307:
		msleep(50);		/*fixme: is it useful? */
		break;
	case SENSOR_OM6802:
		msleep(10);
		reg_w1(gspca_dev, 0x02, 0x73);
		reg17 |= SEN_CLK_EN;
		reg_w1(gspca_dev, 0x17, reg17);
		reg_w1(gspca_dev, 0x01, 0x22);
		msleep(100);
		reg01 = SCL_SEL_OD | S_PDN_INV;
		reg17 &= ~MCK_SIZE_MASK;
		reg17 |= 0x04;		/* clock / 4 */
		break;
	}
	reg01 |= SYS_SEL_48M;
	reg_w1(gspca_dev, 0x01, reg01);
	reg17 |= SEN_CLK_EN;
	reg_w1(gspca_dev, 0x17, reg17);
	reg01 &= ~S_PWR_DN;		/* sensor power on */
	reg_w1(gspca_dev, 0x01, reg01);
	reg01 &= ~SCL_SEL_OD;		/* remove open-drain mode */
	reg_w1(gspca_dev, 0x01, reg01);

	switch (sd->sensor) {
	case SENSOR_HV7131R:
		hv7131r_probe(gspca_dev);	/*fixme: is it useful? */
		break;
	case SENSOR_OM6802:
		msleep(10);
		reg_w1(gspca_dev, 0x01, reg01);
		i2c_w8(gspca_dev, om6802_init0[0]);
		i2c_w8(gspca_dev, om6802_init0[1]);
		msleep(15);
		reg_w1(gspca_dev, 0x02, 0x71);
		msleep(150);
		break;
	case SENSOR_SP80708:
		msleep(100);
		reg_w1(gspca_dev, 0x02, 0x62);
		break;
	}

	/* initialize the sensor */
	i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);

	reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
	reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
	reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
	reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
	if (sd->sensor == SENSOR_ADCM1700) {
		reg_w1(gspca_dev, 0xd2, 0x3a);	/* AE_H_SIZE = 116 */
		reg_w1(gspca_dev, 0xd3, 0x30);	/* AE_V_SIZE = 96 */
	} else {
		reg_w1(gspca_dev, 0xd2, 0x6a);	/* AE_H_SIZE = 212 */
		reg_w1(gspca_dev, 0xd3, 0x50);	/* AE_V_SIZE = 160 */
	}
	reg_w1(gspca_dev, 0xc6, 0x00);
	reg_w1(gspca_dev, 0xc7, 0x00);
	if (sd->sensor == SENSOR_ADCM1700) {
		reg_w1(gspca_dev, 0xc8, 0x2c);	/* AW_H_STOP = 352 */
		reg_w1(gspca_dev, 0xc9, 0x24);	/* AW_V_STOP = 288 */
	} else {
		reg_w1(gspca_dev, 0xc8, 0x50);	/* AW_H_STOP = 640 */
		reg_w1(gspca_dev, 0xc9, 0x3c);	/* AW_V_STOP = 480 */
	}
	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
	switch (sd->sensor) {
	case SENSOR_OM6802:
/*	case SENSOR_OV7648:		* fixme: sometimes */
		break;
	default:
		reg17 |= DEF_EN;
		break;
	}
	reg_w1(gspca_dev, 0x17, reg17);

	reg_w1(gspca_dev, 0x05, 0x00);		/* red */
	reg_w1(gspca_dev, 0x07, 0x00);		/* green */
	reg_w1(gspca_dev, 0x06, 0x00);		/* blue */
	reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);

	setgamma(gspca_dev);

/*fixme: 8 times with all zeroes and 1 or 2 times with normal values */
	for (i = 0; i < 8; i++)
		reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
	switch (sd->sensor) {
	case SENSOR_ADCM1700:
	case SENSOR_OV7660:
	case SENSOR_SP80708:
		reg_w1(gspca_dev, 0x9a, 0x05);
		break;
	case SENSOR_GC0307:
	case SENSOR_MT9V111:
	case SENSOR_MI0360B:
		reg_w1(gspca_dev, 0x9a, 0x07);
		break;
	case SENSOR_OV7630:
	case SENSOR_OV7648:
		reg_w1(gspca_dev, 0x9a, 0x0a);
		break;
	case SENSOR_PO2030N:
	case SENSOR_SOI768:
		reg_w1(gspca_dev, 0x9a, 0x06);
		break;
	default:
		reg_w1(gspca_dev, 0x9a, 0x08);
		break;
	}
	setsharpness(gspca_dev);

	reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
	reg_w1(gspca_dev, 0x05, 0x20);		/* red */
	reg_w1(gspca_dev, 0x07, 0x20);		/* green */
	reg_w1(gspca_dev, 0x06, 0x20);		/* blue */

	init = NULL;
	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
	reg01 |= SYS_SEL_48M | V_TX_EN;
	reg17 &= ~MCK_SIZE_MASK;
	reg17 |= 0x02;			/* clock / 2 */
	switch (sd->sensor) {
	case SENSOR_ADCM1700:
		init = adcm1700_sensor_param1;
		break;
	case SENSOR_GC0307:
		init = gc0307_sensor_param1;
		break;
	case SENSOR_HV7131R:
	case SENSOR_MI0360:
		if (!mode)
			reg01 &= ~SYS_SEL_48M;	/* 640x480: clk 24Mhz */
		reg17 &= ~MCK_SIZE_MASK;
		reg17 |= 0x01;			/* clock / 1 */
		break;
	case SENSOR_MI0360B:
		init = mi0360b_sensor_param1;
		break;
	case SENSOR_MO4000:
		if (mode) {			/* if 320x240 */
			reg01 &= ~SYS_SEL_48M;	/* clk 24Mz */
			reg17 &= ~MCK_SIZE_MASK;
			reg17 |= 0x01;		/* clock / 1 */
		}
		break;
	case SENSOR_MT9V111:
		init = mt9v111_sensor_param1;
		break;
	case SENSOR_OM6802:
		init = om6802_sensor_param1;
		if (!mode) {			/* if 640x480 */
			reg17 &= ~MCK_SIZE_MASK;
			reg17 |= 0x04;		/* clock / 4 */
		} else {
			reg01 &= ~SYS_SEL_48M;	/* clk 24Mz */
			reg17 &= ~MCK_SIZE_MASK;
			reg17 |= 0x02;		/* clock / 2 */
		}
		break;
	case SENSOR_OV7630:
		init = ov7630_sensor_param1;
		break;
	case SENSOR_OV7648:
		init = ov7648_sensor_param1;
		reg17 &= ~MCK_SIZE_MASK;
		reg17 |= 0x01;			/* clock / 1 */
		break;
	case SENSOR_OV7660:
		init = ov7660_sensor_param1;
		break;
	case SENSOR_PO1030:
		init = po1030_sensor_param1;
		break;
	case SENSOR_PO2030N:
		init = po2030n_sensor_param1;
		break;
	case SENSOR_SOI768:
		init = soi768_sensor_param1;
		break;
	case SENSOR_SP80708:
		init = sp80708_sensor_param1;
		break;
	}

	/* more sensor initialization - param1 */
	if (init != NULL) {
		i2c_w_seq(gspca_dev, init);
/*		init = NULL; */
	}

	reg_w(gspca_dev, 0xc0, C0, 6);
	switch (sd->sensor) {
	case SENSOR_ADCM1700:
	case SENSOR_GC0307:
	case SENSOR_SOI768:
		reg_w(gspca_dev, 0xca, CA_adcm1700, 4);
		break;
	case SENSOR_PO2030N:
		reg_w(gspca_dev, 0xca, CA_po2030n, 4);
		break;
	default:
		reg_w(gspca_dev, 0xca, CA, 4);
		break;
	}
	switch (sd->sensor) {
	case SENSOR_ADCM1700:
	case SENSOR_OV7630:
	case SENSOR_OV7648:
	case SENSOR_OV7660:
	case SENSOR_SOI768:
		reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
		break;
	case SENSOR_GC0307:
		reg_w(gspca_dev, 0xce, CE_gc0307, 4);
		break;
	case SENSOR_PO2030N:
		reg_w(gspca_dev, 0xce, CE_po2030n, 4);
		break;
	default:
		reg_w(gspca_dev, 0xce, CE, 4);
					/* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
		break;
	}

	/* here change size mode 0 -> VGA; 1 -> CIF */
	sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40;
	reg_w1(gspca_dev, 0x18, sd->reg18);
	setjpegqual(gspca_dev);

	reg_w1(gspca_dev, 0x17, reg17);
	reg_w1(gspca_dev, 0x01, reg01);
	sd->reg01 = reg01;
	sd->reg17 = reg17;

	sd->pktsz = sd->npkt = 0;
	sd->nchg = sd->short_mark = 0;

	return gspca_dev->usb_err;
}