Exemplo n.º 1
0
static int
saa711x_write_block (struct i2c_client *client,
		     const u8          *data,
		     unsigned int       len)
{
	int ret = -1;
	u8 reg;

	/* the saa711x has an autoincrement function, use it if
	 * the adapter understands raw I2C */
	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		/* do raw I2C, not smbus compatible */
		struct saa711x *decoder = i2c_get_clientdata(client);
		struct i2c_msg msg;
		u8 block_data[32];

		msg.addr = client->addr;
		msg.flags = 0;
		while (len >= 2) {
			msg.buf = (char *) block_data;
			msg.len = 0;
			block_data[msg.len++] = reg = data[0];
			do {
				block_data[msg.len++] =
				    decoder->reg[reg++] = data[1];
				len -= 2;
				data += 2;
			} while (len >= 2 && data[0] == reg &&
				 msg.len < 32);
			if ((ret = i2c_transfer(client->adapter,
						&msg, 1)) < 0)
				break;
		}
	} else {
		/* do some slow I2C emulation kind of thing */
		while (len >= 2) {
			reg = *data++;
			if ((ret = saa711x_write(client, reg,
						 *data++)) < 0)
				break;
			len -= 2;
		}
	}

	return ret;
}
Exemplo n.º 2
0
static int saa711x_writeregs(struct i2c_client *client, const unsigned char *regs)
{
	struct saa711x_state *state = i2c_get_clientdata(client);
	unsigned char reg, data;

	while (*regs != 0x00) {
		reg = *(regs++);
		data = *(regs++);

		/* According with datasheets, reserved regs should be
		   filled with 0 - seems better not to touch on they */
		if (saa711x_has_reg(state->ident,reg)) {
			if (saa711x_write(client, reg, data) < 0)
				return -1;
		} else {
			v4l_dbg(1, debug, client, "tried to access reserved reg 0x%02x\n", reg);
		}
	}
	return 0;
}
Exemplo n.º 3
0
static int
saa711x_command (struct i2c_client *client,
		 unsigned int       cmd,
		 void              *arg)
{
	struct saa711x *decoder = i2c_get_clientdata(client);

	switch (cmd) {

	case 0:
	case DECODER_INIT:
	{
		struct video_decoder_init *init = arg;
		if (NULL != init)
			return saa711x_init_decoder(client, init);
		else {
			struct video_decoder_init vdi;
			vdi.data = saa711x_i2c_init;
			vdi.len = sizeof(saa711x_i2c_init);
			return saa711x_init_decoder(client, &vdi);
		}
	}

	case DECODER_DUMP:
	{
		int i;

		for (i = 0; i < 32; i += 16) {
			int j;

			printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i);
			for (j = 0; j < 16; ++j) {
				printk(" %02x",
				       saa711x_read(client, i + j));
			}
			printk("\n");
		}
	}
		break;

	case DECODER_GET_CAPABILITIES:
	{
		struct video_decoder_capability *cap = arg;

		cap->flags = VIDEO_DECODER_PAL |
			     VIDEO_DECODER_NTSC |
			     VIDEO_DECODER_SECAM |
			     VIDEO_DECODER_AUTO |
			     VIDEO_DECODER_CCIR;
		cap->inputs = 8;
		cap->outputs = 1;
	}
		break;

	case DECODER_GET_STATUS:
	{
		int *iarg = arg;
		int status;
		int res;

		status = saa711x_read(client, 0x1f);
		dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client),
			status);
		res = 0;
		if ((status & (1 << 6)) == 0) {
			res |= DECODER_STATUS_GOOD;
		}
		switch (decoder->norm) {
		case VIDEO_MODE_NTSC:
			res |= DECODER_STATUS_NTSC;
			break;
		case VIDEO_MODE_PAL:
			res |= DECODER_STATUS_PAL;
			break;
		case VIDEO_MODE_SECAM:
			res |= DECODER_STATUS_SECAM;
			break;
		default:
		case VIDEO_MODE_AUTO:
			if ((status & (1 << 5)) != 0) {
				res |= DECODER_STATUS_NTSC;
			} else {
				res |= DECODER_STATUS_PAL;
			}
			break;
		}
		if ((status & (1 << 0)) != 0) {
			res |= DECODER_STATUS_COLOR;
		}
		*iarg = res;
	}
		break;

	case DECODER_SET_GPIO:
	{
		int *iarg = arg;
		if (0 != *iarg) {
			saa711x_write(client, 0x11,
				(decoder->reg[0x11] | 0x80));
		} else {
			saa711x_write(client, 0x11,
				(decoder->reg[0x11] & 0x7f));
		}
		break;
	}

	case DECODER_SET_VBI_BYPASS:
	{
		int *iarg = arg;
		if (0 != *iarg) {
			saa711x_write(client, 0x13,
				(decoder->reg[0x13] & 0xf0) | 0x0a);
		} else {
			saa711x_write(client, 0x13,
				(decoder->reg[0x13] & 0xf0));
		}
		break;
	}

	case DECODER_SET_NORM:
	{
		int *iarg = arg;

		switch (*iarg) {

		case VIDEO_MODE_NTSC:
			saa711x_write(client, 0x08,
				      (decoder->reg[0x08] & 0x3f) | 0x40);
			saa711x_write(client, 0x0e,
				      (decoder->reg[0x0e] & 0x8f));
			break;

		case VIDEO_MODE_PAL:
			saa711x_write(client, 0x08,
				      (decoder->reg[0x08] & 0x3f) | 0x00);
			saa711x_write(client, 0x0e,
				      (decoder->reg[0x0e] & 0x8f));
			break;

		case VIDEO_MODE_SECAM:
			saa711x_write(client, 0x08,
				      (decoder->reg[0x08] & 0x3f) | 0x00);
			saa711x_write(client, 0x0e,
				      (decoder->reg[0x0e] & 0x8f) | 0x50);
			break;

		case VIDEO_MODE_AUTO:
			saa711x_write(client, 0x08,
				      (decoder->reg[0x08] & 0x3f) | 0x80);
			saa711x_write(client, 0x0e,
				      (decoder->reg[0x0e] & 0x8f));
			break;

		default:
			return -EINVAL;

		}
		decoder->norm = *iarg;
	}
		break;

	case DECODER_SET_INPUT:
	{
		int *iarg = arg;
		if (*iarg < 0 || *iarg > 9) {
			return -EINVAL;
		}
		if (decoder->input != *iarg) {
			decoder->input = *iarg;
			/* select mode */
			saa711x_write(client, 0x02,
				      (decoder->reg[0x02] & 0xf0) | decoder->input);
			/* bypass chrominance trap for modes 4..7 */
			saa711x_write(client, 0x09,
				      (decoder->reg[0x09] & 0x7f) | ((decoder->input > 3) ? 0x80 : 0));
		}
	}
		break;

	case DECODER_SET_OUTPUT:
	{
		int *iarg = arg;

		/* not much choice of outputs */
		if (*iarg != 0) {
			return -EINVAL;
		}
	}
		break;

	case DECODER_ENABLE_OUTPUT:
	{
		int *iarg = arg;
		int enable = (*iarg != 0);

		if (decoder->enable != enable) {
			decoder->enable = enable;

			/* RJ: If output should be disabled (for
			 * playing videos), we also need a open PLL.
			 * The input is set to 0 (where no input
			 * source is connected), although this
			 * is not necessary.
			 *
			 * If output should be enabled, we have to
			 * reverse the above.
			 */

			if (decoder->enable) {
				saa711x_write(client, 0x02,
					      (decoder->
					       reg[0x02] & 0xf8) |
					      decoder->input);
				saa711x_write(client, 0x08,
					      (decoder->reg[0x08] & 0xfb));
				saa711x_write(client, 0x11,
					      (decoder->
					       reg[0x11] & 0xf3) | 0x0c);
			} else {
				saa711x_write(client, 0x02,
					      (decoder->reg[0x02] & 0xf8));
				saa711x_write(client, 0x08,
					      (decoder->
					       reg[0x08] & 0xfb) | 0x04);
				saa711x_write(client, 0x11,
					      (decoder->reg[0x11] & 0xf3));
			}
		}
	}
		break;

	case DECODER_SET_PICTURE:
	{
		struct video_picture *pic = arg;

		if (decoder->bright != pic->brightness) {
			/* We want 0 to 255 we get 0-65535 */
			decoder->bright = pic->brightness;
			saa711x_write(client, 0x0a, decoder->bright >> 8);
		}
		if (decoder->contrast != pic->contrast) {
			/* We want 0 to 127 we get 0-65535 */
			decoder->contrast = pic->contrast;
			saa711x_write(client, 0x0b,
				      decoder->contrast >> 9);
		}
		if (decoder->sat != pic->colour) {
			/* We want 0 to 127 we get 0-65535 */
			decoder->sat = pic->colour;
			saa711x_write(client, 0x0c, decoder->sat >> 9);
		}