Пример #1
0
static int
saa7185_detect_client (struct i2c_adapter *adapter,
		       int                 address,
		       int                 kind)
{
	int i;
	struct i2c_client *client;
	struct saa7185 *encoder;

	dprintk(1,
		KERN_INFO
		"saa7185.c: detecting saa7185 client on address 0x%x\n",
		address << 1);

	/* Check if the adapter supports the needed features */
	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
		return 0;

	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
	if (client == 0)
		return -ENOMEM;
	client->addr = address;
	client->adapter = adapter;
	client->driver = &i2c_driver_saa7185;
	strlcpy(I2C_NAME(client), "saa7185", sizeof(I2C_NAME(client)));

	encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL);
	if (encoder == NULL) {
		kfree(client);
		return -ENOMEM;
	}
	encoder->norm = VIDEO_MODE_NTSC;
	encoder->enable = 1;
	i2c_set_clientdata(client, encoder);

	i = i2c_attach_client(client);
	if (i) {
		kfree(client);
		kfree(encoder);
		return i;
	}

	i = saa7185_write_block(client, init_common, sizeof(init_common));
	if (i >= 0) {
		i = saa7185_write_block(client, init_ntsc,
					sizeof(init_ntsc));
	}
	if (i < 0) {
		dprintk(1, KERN_ERR "%s_attach: init error %d\n",
			I2C_NAME(client), i);
	} else {
		dprintk(1,
			KERN_INFO
			"%s_attach: chip version %d at address 0x%x\n",
			I2C_NAME(client), saa7185_read(client) >> 5,
			client->addr << 1);
	}

	return 0;
}
Пример #2
0
static int
saa7111_detect_client (struct i2c_adapter *adapter,
                       int                 address,
                       int                 kind)
{
    int i;
    struct i2c_client *client;
    struct saa7111 *decoder;
    struct video_decoder_init vdi;

    dprintk(1,
            KERN_INFO
            "saa7111.c: detecting saa7111 client on address 0x%x\n",
            address << 1);

    /* Check if the adapter supports the needed features */
    if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
        return 0;

    client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
    if (client == 0)
        return -ENOMEM;
    client->addr = address;
    client->adapter = adapter;
    client->driver = &i2c_driver_saa7111;
    strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client)));

    decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL);
    if (decoder == NULL) {
        kfree(client);
        return -ENOMEM;
    }
    decoder->norm = VIDEO_MODE_NTSC;
    decoder->input = 0;
    decoder->enable = 1;
    i2c_set_clientdata(client, decoder);

    i = i2c_attach_client(client);
    if (i) {
        kfree(client);
        kfree(decoder);
        return i;
    }

    vdi.data = saa7111_i2c_init;
    vdi.len = sizeof(saa7111_i2c_init);
    i = saa7111_init_decoder(client, &vdi);
    if (i < 0) {
        dprintk(1, KERN_ERR "%s_attach error: init status %d\n",
                I2C_NAME(client), i);
    } else {
        dprintk(1,
                KERN_INFO
                "%s_attach: chip version %x at address 0x%x\n",
                I2C_NAME(client), saa7111_read(client, 0x00) >> 4,
                client->addr << 1);
    }

    return 0;
}
Пример #3
0
static int
bt856_attach_adapter (struct i2c_adapter *adapter)
{
	dprintk(1,
		KERN_INFO
		"bt856.c: starting probe for adapter %s (0x%x)\n",
		I2C_NAME(adapter), adapter->id);
	return i2c_probe(adapter, &addr_data, &bt856_detect_client);
}
Пример #4
0
static void
bt856_dump (struct i2c_client *client)
{
	int i;
	struct bt856 *encoder = i2c_get_clientdata(client);

	printk(KERN_INFO "%s: register dump:", I2C_NAME(client));
	for (i = 0xd6; i <= 0xde; i += 2)
		printk(" %02x", encoder->reg[i - REG_OFFSET]);
	printk("\n");
}
Пример #5
0
static int
bt856_detect_client (struct i2c_adapter *adapter,
		     int                 address,
		     int                 kind)
{
	int i;
	struct i2c_client *client;
	struct bt856 *encoder;

	dprintk(1,
		KERN_INFO
		"bt856.c: detecting bt856 client on address 0x%x\n",
		address << 1);

	/* Check if the adapter supports the needed features */
	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
		return 0;

	client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
	if (client == 0)
		return -ENOMEM;
	memset(client, 0, sizeof(struct i2c_client));
	client->addr = address;
	client->adapter = adapter;
	client->driver = &i2c_driver_bt856;
	client->flags = I2C_CLIENT_ALLOW_USE;
	strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client)));

	encoder = kmalloc(sizeof(struct bt856), GFP_KERNEL);
	if (encoder == NULL) {
		kfree(client);
		return -ENOMEM;
	}
	memset(encoder, 0, sizeof(struct bt856));
	encoder->norm = VIDEO_MODE_NTSC;
	encoder->enable = 1;
	i2c_set_clientdata(client, encoder);

	i = i2c_attach_client(client);
	if (i) {
		kfree(client);
		kfree(encoder);
		return i;
	}

	bt856_write(client, 0xdc, 0x18);
	bt856_write(client, 0xda, 0);
	bt856_write(client, 0xde, 0);

	bt856_setbit(client, 0xdc, 3, 1);
	//bt856_setbit(client, 0xdc, 6, 0);
	bt856_setbit(client, 0xdc, 4, 1);

	switch (encoder->norm) {

	case VIDEO_MODE_NTSC:
		bt856_setbit(client, 0xdc, 2, 0);
		break;

	case VIDEO_MODE_PAL:
		bt856_setbit(client, 0xdc, 2, 1);
		break;
	}

	bt856_setbit(client, 0xdc, 1, 1);
	bt856_setbit(client, 0xde, 4, 0);
	bt856_setbit(client, 0xde, 3, 1);

	if (debug != 0)
		bt856_dump(client);

	dprintk(1, KERN_INFO "%s_attach: at address 0x%x\n", I2C_NAME(client),
		client->addr << 1);

	return 0;
}
Пример #6
0
static int
bt856_command (struct i2c_client *client,
	       unsigned int       cmd,
	       void              *arg)
{
	struct bt856 *encoder = i2c_get_clientdata(client);

	switch (cmd) {

	case 0:
		/* This is just for testing!!! */
		dprintk(1, KERN_INFO "bt856: init\n");
		bt856_write(client, 0xdc, 0x18);
		bt856_write(client, 0xda, 0);
		bt856_write(client, 0xde, 0);

		bt856_setbit(client, 0xdc, 3, 1);
		//bt856_setbit(client, 0xdc, 6, 0);
		bt856_setbit(client, 0xdc, 4, 1);

		switch (encoder->norm) {

		case VIDEO_MODE_NTSC:
			bt856_setbit(client, 0xdc, 2, 0);
			break;

		case VIDEO_MODE_PAL:
			bt856_setbit(client, 0xdc, 2, 1);
			break;
		}

		bt856_setbit(client, 0xdc, 1, 1);
		bt856_setbit(client, 0xde, 4, 0);
		bt856_setbit(client, 0xde, 3, 1);
		if (debug != 0)
			bt856_dump(client);
		break;

	case ENCODER_GET_CAPABILITIES:
	{
		struct video_encoder_capability *cap = arg;

		dprintk(1, KERN_INFO "%s: get capabilities\n",
			I2C_NAME(client));

		cap->flags = VIDEO_ENCODER_PAL |
			     VIDEO_ENCODER_NTSC |
			     VIDEO_ENCODER_CCIR;
		cap->inputs = 2;
		cap->outputs = 1;
	}
		break;

	case ENCODER_SET_NORM:
	{
		int *iarg = arg;

		dprintk(1, KERN_INFO "%s: set norm %d\n", I2C_NAME(client),
			*iarg);

		switch (*iarg) {

		case VIDEO_MODE_NTSC:
			bt856_setbit(client, 0xdc, 2, 0);
			break;

		case VIDEO_MODE_PAL:
			bt856_setbit(client, 0xdc, 2, 1);
			bt856_setbit(client, 0xda, 0, 0);
			//bt856_setbit(client, 0xda, 0, 1);
			break;

		default:
			return -EINVAL;

		}
		encoder->norm = *iarg;
		if (debug != 0)
			bt856_dump(client);
	}
		break;

	case ENCODER_SET_INPUT:
	{
		int *iarg = arg;

		dprintk(1, KERN_INFO "%s: set input %d\n", I2C_NAME(client),
			*iarg);

		/* We only have video bus.
		 * iarg = 0: input is from bt819
		 * iarg = 1: input is from ZR36060 */

		switch (*iarg) {

		case 0:
			bt856_setbit(client, 0xde, 4, 0);
			bt856_setbit(client, 0xde, 3, 1);
			bt856_setbit(client, 0xdc, 3, 1);
			bt856_setbit(client, 0xdc, 6, 0);
			break;
		case 1:
			bt856_setbit(client, 0xde, 4, 0);
			bt856_setbit(client, 0xde, 3, 1);
			bt856_setbit(client, 0xdc, 3, 1);
			bt856_setbit(client, 0xdc, 6, 1);
			break;
		case 2:	// Color bar
			bt856_setbit(client, 0xdc, 3, 0);
			bt856_setbit(client, 0xde, 4, 1);
			break;
		default:
			return -EINVAL;

		}

		if (debug != 0)
			bt856_dump(client);
	}
		break;

	case ENCODER_SET_OUTPUT:
	{
		int *iarg = arg;

		dprintk(1, KERN_INFO "%s: set output %d\n", I2C_NAME(client),
			*iarg);

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

	case ENCODER_ENABLE_OUTPUT:
	{
		int *iarg = arg;

		encoder->enable = !!*iarg;

		dprintk(1, KERN_INFO "%s: enable output %d\n",
			I2C_NAME(client), encoder->enable);
	}
		break;

	default:
		return -EINVAL;
	}

	return 0;
}
static int
vpx3220_command (struct i2c_client *client,
		 unsigned int       cmd,
		 void              *arg)
{
	struct vpx3220 *decoder = i2c_get_clientdata(client);

	switch (cmd) {
	case 0:
	{
		vpx3220_write_block(client, init_common,
				    sizeof(init_common));
		vpx3220_write_fp_block(client, init_fp,
				       sizeof(init_fp) >> 1);
		switch (decoder->norm) {
			
		case VIDEO_MODE_NTSC:
			vpx3220_write_fp_block(client, init_ntsc,
					       sizeof(init_ntsc) >> 1);
			break;

		case VIDEO_MODE_PAL:
			vpx3220_write_fp_block(client, init_pal,
				       	       sizeof(init_pal) >> 1);
			break;
		case VIDEO_MODE_SECAM:
			vpx3220_write_fp_block(client, init_secam,
					       sizeof(init_secam) >> 1);
			break;
		default:
			vpx3220_write_fp_block(client, init_pal,
				       	       sizeof(init_pal) >> 1);
			break;
		}
	}		
		break;

	case DECODER_DUMP:
	{
		vpx3220_dump_i2c(client);
	}
		break;

	case DECODER_GET_CAPABILITIES:
	{
		struct video_decoder_capability *cap = arg;

		dprintk(1, KERN_DEBUG "%s: DECODER_GET_CAPABILITIES\n",
			I2C_NAME(client));

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

	case DECODER_GET_STATUS:
	{
		int res = 0, status;

		dprintk(1, KERN_INFO "%s: DECODER_GET_STATUS\n",
			I2C_NAME(client));

		status = vpx3220_fp_read(client, 0x0f3);

		dprintk(1, KERN_INFO "%s: status: 0x%04x\n", I2C_NAME(client),
			status);

		if (status < 0)
			return status;

		if ((status & 0x20) == 0) {
			res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR;

			switch (status & 0x18) {

			case 0x00:
			case 0x10:
			case 0x14:
			case 0x18:
				res |= DECODER_STATUS_PAL;
				break;

			case 0x08:
				res |= DECODER_STATUS_SECAM;
				break;

			case 0x04:
			case 0x0c:
			case 0x1c:
				res |= DECODER_STATUS_NTSC;
				break;
			}
		}

		*(int *) arg = res;
	}
		break;

	case DECODER_SET_NORM:
	{
		int *iarg = arg, data;

		dprintk(1, KERN_DEBUG "%s: DECODER_SET_NORM %d\n",
			I2C_NAME(client), *iarg);
		switch (*iarg) {

		case VIDEO_MODE_NTSC:
			vpx3220_write_fp_block(client, init_ntsc,
					       sizeof(init_ntsc) >> 1);
			dprintk(1, KERN_INFO "%s: norm switched to NTSC\n",
				I2C_NAME(client));
			break;

		case VIDEO_MODE_PAL:
			vpx3220_write_fp_block(client, init_pal,
					       sizeof(init_pal) >> 1);
			dprintk(1, KERN_INFO "%s: norm switched to PAL\n",
				I2C_NAME(client));
			break;

		case VIDEO_MODE_SECAM:
			vpx3220_write_fp_block(client, init_secam,
					       sizeof(init_secam) >> 1);
			dprintk(1, KERN_INFO "%s: norm switched to SECAM\n",
				I2C_NAME(client));
			break;

		case VIDEO_MODE_AUTO:
			/* FIXME This is only preliminary support */
			data = vpx3220_fp_read(client, 0xf2) & 0x20;
			vpx3220_fp_write(client, 0xf2, 0x00c0 | data);
			dprintk(1, KERN_INFO "%s: norm switched to Auto\n",
				I2C_NAME(client));
			break;

		default:
			return -EINVAL;

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

	case DECODER_SET_INPUT:
	{
		int *iarg = arg, data;

		/* RJ:  *iarg = 0: ST8 (PCTV) input
		 *iarg = 1: COMPOSITE  input
		 *iarg = 2: SVHS       input  */

		const int input[3][2] = {
			{0x0c, 0},
			{0x0d, 0},
			{0x0e, 1}
		};

		if (*iarg < 0 || *iarg > 2)
			return -EINVAL;

		dprintk(1, KERN_INFO "%s: input switched to %s\n",
			I2C_NAME(client), inputs[*iarg]);

		vpx3220_write(client, 0x33, input[*iarg][0]);

		data = vpx3220_fp_read(client, 0xf2) & ~(0x0020);
		if (data < 0)
			return data;
		/* 0x0010 is required to latch the setting */
		vpx3220_fp_write(client, 0xf2,
				 data | (input[*iarg][1] << 5) | 0x0010);

		udelay(10);
	}
		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;

		dprintk(1, KERN_DEBUG "%s: DECODER_ENABLE_OUTPUT %d\n",
			I2C_NAME(client), *iarg);

		vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00));
	}
		break;

	case DECODER_SET_PICTURE:
	{
		struct video_picture *pic = arg;

		if (decoder->bright != pic->brightness) {
			/* We want -128 to 128 we get 0-65535 */
			decoder->bright = pic->brightness;
			vpx3220_write(client, 0xe6,
				      (decoder->bright - 32768) >> 8);
		}
		if (decoder->contrast != pic->contrast) {
			/* We want 0 to 64 we get 0-65535 */
			/* Bit 7 and 8 is for noise shaping */
			decoder->contrast = pic->contrast;
			vpx3220_write(client, 0xe7,
				      (decoder->contrast >> 10) + 192);
		}
		if (decoder->sat != pic->colour) {
			/* We want 0 to 4096 we get 0-65535 */
			decoder->sat = pic->colour;
			vpx3220_fp_write(client, 0xa0,
					 decoder->sat >> 4);
		}
Пример #8
0
static int
saa7111_command (struct i2c_client *client,
                 unsigned int       cmd,
                 void              *arg)
{
    struct saa7111 *decoder = i2c_get_clientdata(client);

    switch (cmd) {

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

    case DECODER_DUMP:
    {
        int i;

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

            printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i);
            for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) {
                printk(" %02x",
                       saa7111_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 = saa7111_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) {
            saa7111_write(client, 0x11,
                          (decoder->reg[0x11] | 0x80));
        } else {
            saa7111_write(client, 0x11,
                          (decoder->reg[0x11] & 0x7f));
        }
        break;
    }

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

    case DECODER_SET_NORM:
    {
        int *iarg = arg;

        switch (*iarg) {

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

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

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

        case VIDEO_MODE_AUTO:
            saa7111_write(client, 0x08,
                          (decoder->reg[0x08] & 0x3f) | 0x80);
            saa7111_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 > 7) {
            return -EINVAL;
        }

        if (decoder->input != *iarg) {
            decoder->input = *iarg;
            /* select mode */
            saa7111_write(client, 0x02,
                          (decoder->
                           reg[0x02] & 0xf8) | decoder->input);
            /* bypass chrominance trap for modes 4..7 */
            saa7111_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) {
                saa7111_write(client, 0x02,
                              (decoder->
                               reg[0x02] & 0xf8) |
                              decoder->input);
                saa7111_write(client, 0x08,
                              (decoder->reg[0x08] & 0xfb));
                saa7111_write(client, 0x11,
                              (decoder->
                               reg[0x11] & 0xf3) | 0x0c);
            } else {
                saa7111_write(client, 0x02,
                              (decoder->reg[0x02] & 0xf8));
                saa7111_write(client, 0x08,
                              (decoder->
                               reg[0x08] & 0xfb) | 0x04);
                saa7111_write(client, 0x11,
                              (decoder->reg[0x11] & 0xf3));
            }
        }
    }
    break;

    case DECODER_SET_PICTURE:
    {
        struct video_picture *pic = arg;

        /* We want 0 to 255 we get 0-65535 */
        saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8);
        /* We want 0 to 127 we get 0-65535 */
        saa7111_write(client, 0x0b, pic->contrast >> 9);
        /* We want 0 to 127 we get 0-65535 */
        saa7111_write(client, 0x0c, pic->colour >> 9);
        /* We want -128 to 127 we get 0-65535 */
        saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8);
    }
    break;

    default:
        return -EINVAL;
    }

    return 0;
}
Пример #9
0
static int
saa7185_detect_client (struct i2c_adapter *adapter,
		       int                 address,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
		       unsigned short      flags,
#endif
		       int                 kind)
{
	int i;
	struct i2c_client *client;
	struct saa7185 *encoder;

	dprintk(1,
		KERN_INFO
		"saa7185.c: detecting saa7185 client on address 0x%x\n",
		address << 1);

	/* Check if the adapter supports the needed features */
	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
		return 0;

	client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
	if (client == 0)
		return -ENOMEM;
	memset(client, 0, sizeof(struct i2c_client));
	client->addr = address;
	client->adapter = adapter;
	client->driver = &i2c_driver_saa7185;
	client->flags = I2C_CLIENT_ALLOW_USE;
	client->id = saa7185_i2c_id++;
	snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
		"saa7185[%d]", client->id);

	encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL);
	if (encoder == NULL) {
		kfree(client);
		return -ENOMEM;
	}
	memset(encoder, 0, sizeof(struct saa7185));
	encoder->norm = VIDEO_MODE_NTSC;
	encoder->enable = 1;
	i2c_set_clientdata(client, encoder);

	i = i2c_attach_client(client);
	if (i) {
		kfree(client);
		kfree(encoder);
		return i;
	}

	i = saa7185_write_block(client, init_common, sizeof(init_common));
	if (i >= 0) {
		i = saa7185_write_block(client, init_ntsc,
					sizeof(init_ntsc));
	}
	if (i < 0) {
		dprintk(1, KERN_ERR "%s_attach: init error %d\n",
			I2C_NAME(client), i);
	} else {
		dprintk(1,
			KERN_INFO
			"%s_attach: chip version %d at address 0x%x\n",
			I2C_NAME(client), saa7185_read(client) >> 5,
			client->addr << 1);
	}

	return 0;
}
Пример #10
0
static int
saa7110_command (struct i2c_client *client,
		 unsigned int       cmd,
		 void              *arg)
{
	struct saa7110 *decoder = i2c_get_clientdata(client);
	int v;

	switch (cmd) {
	case 0:
		//saa7110_write_block(client, initseq, sizeof(initseq));
		break;

	case DECODER_GET_CAPABILITIES:
	{
		struct video_decoder_capability *dc = arg;

		dc->flags =
		    VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |
		    VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
		dc->inputs = SAA7110_MAX_INPUT;
		dc->outputs = SAA7110_MAX_OUTPUT;
	}
		break;

	case DECODER_GET_STATUS:
	{
		int status;
		int res = 0;

		status = saa7110_read(client);
		dprintk(1, KERN_INFO "%s: status=0x%02x norm=%d\n",
			I2C_NAME(client), status, decoder->norm);
		if (!(status & 0x40))
			res |= DECODER_STATUS_GOOD;
		if (status & 0x03)
			res |= DECODER_STATUS_COLOR;

		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;
		}
		*(int *) arg = res;
	}
		break;

	case DECODER_SET_NORM:
		v = *(int *) arg;
		if (decoder->norm != v) {
			decoder->norm = v;
			//saa7110_write(client, 0x06, 0x03);
			switch (v) {
			case VIDEO_MODE_NTSC:
				saa7110_write(client, 0x0D, 0x86);
				saa7110_write(client, 0x0F, 0x50);
				saa7110_write(client, 0x11, 0x2C);
				//saa7110_write(client, 0x2E, 0x81);
				dprintk(1,
					KERN_INFO "%s: switched to NTSC\n",
					I2C_NAME(client));
				break;
			case VIDEO_MODE_PAL:
				saa7110_write(client, 0x0D, 0x86);
				saa7110_write(client, 0x0F, 0x10);
				saa7110_write(client, 0x11, 0x59);
				//saa7110_write(client, 0x2E, 0x9A);
				dprintk(1,
					KERN_INFO "%s: switched to PAL\n",
					I2C_NAME(client));
				break;
			case VIDEO_MODE_SECAM:
				saa7110_write(client, 0x0D, 0x87);
				saa7110_write(client, 0x0F, 0x10);
				saa7110_write(client, 0x11, 0x59);
				//saa7110_write(client, 0x2E, 0x9A);
				dprintk(1,
					KERN_INFO
					"%s: switched to SECAM\n",
					I2C_NAME(client));
				break;
			case VIDEO_MODE_AUTO:
				dprintk(1,
					KERN_INFO
					"%s: TV standard detection...\n",
					I2C_NAME(client));
				decoder->norm = determine_norm(client);
				*(int *) arg = decoder->norm;
				break;
			default:
				return -EPERM;
			}
		}
		break;

	case DECODER_SET_INPUT:
		v = *(int *) arg;
		if (v < 0 || v > SAA7110_MAX_INPUT) {
			dprintk(1,
				KERN_INFO "%s: input=%d not available\n",
				I2C_NAME(client), v);
			return -EINVAL;
		}
		if (decoder->input != v) {
			saa7110_selmux(client, v);
			dprintk(1, KERN_INFO "%s: switched to input=%d\n",
				I2C_NAME(client), v);
		}
		break;

	case DECODER_SET_OUTPUT:
		v = *(int *) arg;
		/* not much choice of outputs */
		if (v != 0)
			return -EINVAL;
		break;

	case DECODER_ENABLE_OUTPUT:
		v = *(int *) arg;
		if (decoder->enable != v) {
			decoder->enable = v;
			saa7110_write(client, 0x0E, v ? 0x18 : 0x80);
			dprintk(1, KERN_INFO "%s: YUV %s\n", I2C_NAME(client),
				v ? "on" : "off");
		}
		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;
			saa7110_write(client, 0x19, decoder->bright >> 8);
		}
		if (decoder->contrast != pic->contrast) {
			/* We want 0 to 127 we get 0-65535 */
			decoder->contrast = pic->contrast;
			saa7110_write(client, 0x13,
				      decoder->contrast >> 9);
		}
		if (decoder->sat != pic->colour) {
			/* We want 0 to 127 we get 0-65535 */
			decoder->sat = pic->colour;
			saa7110_write(client, 0x12, decoder->sat >> 9);
		}
Пример #11
0
static int
determine_norm (struct i2c_client *client)
{
	DEFINE_WAIT(wait);
	struct saa7110 *decoder = i2c_get_clientdata(client);
	int status;

	/* mode changed, start automatic detection */
	saa7110_write_block(client, initseq, sizeof(initseq));
	saa7110_selmux(client, decoder->input);
	prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
	schedule_timeout(HZ/4);
	finish_wait(&decoder->wq, &wait);
	status = saa7110_read(client);
	if (status & 0x40) {
		dprintk(1, KERN_INFO "%s: status=0x%02x (no signal)\n",
			I2C_NAME(client), status);
		return decoder->norm;	// no change
	}
	if ((status & 3) == 0) {
		saa7110_write(client, 0x06, 0x83);
		if (status & 0x20) {
			dprintk(1,
				KERN_INFO
				"%s: status=0x%02x (NTSC/no color)\n",
				I2C_NAME(client), status);
			//saa7110_write(client,0x2E,0x81);
			return VIDEO_MODE_NTSC;
		}
		dprintk(1, KERN_INFO "%s: status=0x%02x (PAL/no color)\n",
			I2C_NAME(client), status);
		//saa7110_write(client,0x2E,0x9A);
		return VIDEO_MODE_PAL;
	}
	//saa7110_write(client,0x06,0x03);
	if (status & 0x20) {	/* 60Hz */
		dprintk(1, KERN_INFO "%s: status=0x%02x (NTSC)\n",
			I2C_NAME(client), status);
		saa7110_write(client, 0x0D, 0x86);
		saa7110_write(client, 0x0F, 0x50);
		saa7110_write(client, 0x11, 0x2C);
		//saa7110_write(client,0x2E,0x81);
		return VIDEO_MODE_NTSC;
	}

	/* 50Hz -> PAL/SECAM */
	saa7110_write(client, 0x0D, 0x86);
	saa7110_write(client, 0x0F, 0x10);
	saa7110_write(client, 0x11, 0x59);
	//saa7110_write(client,0x2E,0x9A);

	prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
	schedule_timeout(HZ/4);
	finish_wait(&decoder->wq, &wait);

	status = saa7110_read(client);
	if ((status & 0x03) == 0x01) {
		dprintk(1, KERN_INFO "%s: status=0x%02x (SECAM)\n",
			I2C_NAME(client), status);
		saa7110_write(client, 0x0D, 0x87);
		return VIDEO_MODE_SECAM;
	}
	dprintk(1, KERN_INFO "%s: status=0x%02x (PAL)\n", I2C_NAME(client),
		status);
	return VIDEO_MODE_PAL;
}
Пример #12
0
static int
saa7114_command (struct i2c_client *client,
		 unsigned int       cmd,
		 void              *arg)
{
	struct saa7114 *decoder = i2c_get_clientdata(client);

	switch (cmd) {

	case 0:
		//dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client));
		//saa7114_write_block(client, init, sizeof(init));
		break;

	case DECODER_DUMP:
	{
		int i;

		dprintk(1, KERN_INFO "%s: decoder dump\n", I2C_NAME(client));

		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",
				       saa7114_read(client, i + j));
			}
			printk("\n");
		}
	}
		break;

	case DECODER_GET_CAPABILITIES:
	{
		struct video_decoder_capability *cap = arg;

		dprintk(1, KERN_DEBUG "%s: decoder get capabilities\n",
			I2C_NAME(client));

		cap->flags = VIDEO_DECODER_PAL |
			     VIDEO_DECODER_NTSC |
			     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 = saa7114_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_NORM:
	{
		int *iarg = arg;

		short int hoff = 0, voff = 0, w = 0, h = 0;

		dprintk(1, KERN_DEBUG "%s: decoder set norm ",
			I2C_NAME(client));
		switch (*iarg) {

		case VIDEO_MODE_NTSC:
			dprintk(1, "NTSC\n");
			decoder->reg[REG_ADDR(0x06)] =
			    SAA_7114_NTSC_HSYNC_START;
			decoder->reg[REG_ADDR(0x07)] =
			    SAA_7114_NTSC_HSYNC_STOP;

			decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8;	// PLL free when playback, PLL close when capture

			decoder->reg[REG_ADDR(0x0e)] = 0x85;
			decoder->reg[REG_ADDR(0x0f)] = 0x24;

			hoff = SAA_7114_NTSC_HOFFSET;
			voff = SAA_7114_NTSC_VOFFSET;
			w = SAA_7114_NTSC_WIDTH;
			h = SAA_7114_NTSC_HEIGHT;

			break;

		case VIDEO_MODE_PAL:
			dprintk(1, "PAL\n");
			decoder->reg[REG_ADDR(0x06)] =
			    SAA_7114_PAL_HSYNC_START;
			decoder->reg[REG_ADDR(0x07)] =
			    SAA_7114_PAL_HSYNC_STOP;

			decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8;	// PLL free when playback, PLL close when capture

			decoder->reg[REG_ADDR(0x0e)] = 0x81;
			decoder->reg[REG_ADDR(0x0f)] = 0x24;

			hoff = SAA_7114_PAL_HOFFSET;
			voff = SAA_7114_PAL_VOFFSET;
			w = SAA_7114_PAL_WIDTH;
			h = SAA_7114_PAL_HEIGHT;

			break;

		default:
			dprintk(1, " Unknown video mode!!!\n");
			return -EINVAL;

		}


		decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff);	// hoffset low
		decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f;	// hoffset high
		decoder->reg[REG_ADDR(0x96)] = LOBYTE(w);	// width low
		decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f;	// width high
		decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff);	// voffset low
		decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f;	// voffset high
		decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2);	// height low
		decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f;	// height high
		decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w);	// out width low
		decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f;	// out width high
		decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h);	// out height low
		decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f;	// out height high

		decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff);	// hoffset low
		decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f;	// hoffset high
		decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w);	// width low
		decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f;	// width high
		decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff);	// voffset low
		decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f;	// voffset high
		decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2);	// height low
		decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f;	// height high
		decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w);	// out width low
		decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f;	// out width high
		decoder->reg[REG_ADDR(0xce)] = LOBYTE(h);	// out height low
		decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f;	// out height high


		saa7114_write(client, 0x80, 0x06);	// i-port and scaler back end clock selection, task A&B off
		saa7114_write(client, 0x88, 0xd8);	// sw reset scaler
		saa7114_write(client, 0x88, 0xf8);	// sw reset scaler release

		saa7114_write_block(client, decoder->reg + (0x06 << 1),
				    3 << 1);
		saa7114_write_block(client, decoder->reg + (0x0e << 1),
				    2 << 1);
		saa7114_write_block(client, decoder->reg + (0x5a << 1),
				    2 << 1);

		saa7114_write_block(client, decoder->reg + (0x94 << 1),
				    (0x9f + 1 - 0x94) << 1);
		saa7114_write_block(client, decoder->reg + (0xc4 << 1),
				    (0xcf + 1 - 0xc4) << 1);

		saa7114_write(client, 0x88, 0xd8);	// sw reset scaler
		saa7114_write(client, 0x88, 0xf8);	// sw reset scaler release
		saa7114_write(client, 0x80, 0x36);	// i-port and scaler back end clock selection

		decoder->norm = *iarg;
	}
		break;

	case DECODER_SET_INPUT:
	{
		int *iarg = arg;

		dprintk(1, KERN_DEBUG "%s: decoder set input (%d)\n",
			I2C_NAME(client), *iarg);
		if (*iarg < 0 || *iarg > 7) {
			return -EINVAL;
		}

		if (decoder->input != *iarg) {
			dprintk(1, KERN_DEBUG "%s: now setting %s input\n",
				I2C_NAME(client),
				*iarg >= 6 ? "S-Video" : "Composite");
			decoder->input = *iarg;

			/* select mode */
			decoder->reg[REG_ADDR(0x02)] =
			    (decoder->
			     reg[REG_ADDR(0x02)] & 0xf0) | (decoder->
							    input <
							    6 ? 0x0 : 0x9);
			saa7114_write(client, 0x02,
				      decoder->reg[REG_ADDR(0x02)]);

			/* bypass chrominance trap for modes 6..9 */
			decoder->reg[REG_ADDR(0x09)] =
			    (decoder->
			     reg[REG_ADDR(0x09)] & 0x7f) | (decoder->
							    input <
							    6 ? 0x0 :
							    0x80);
			saa7114_write(client, 0x09,
				      decoder->reg[REG_ADDR(0x09)]);

			decoder->reg[REG_ADDR(0x0e)] =
			    decoder->input <
			    6 ? decoder->
			    reg[REG_ADDR(0x0e)] | 1 : decoder->
			    reg[REG_ADDR(0x0e)] & ~1;
			saa7114_write(client, 0x0e,
				      decoder->reg[REG_ADDR(0x0e)]);
		}
	}
		break;

	case DECODER_SET_OUTPUT:
	{
		int *iarg = arg;

		dprintk(1, KERN_DEBUG "%s: decoder set output\n",
			I2C_NAME(client));

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

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

		dprintk(1, KERN_DEBUG "%s: decoder %s output\n",
			I2C_NAME(client), enable ? "enable" : "disable");

		decoder->playback = !enable;

		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) {
				decoder->reg[REG_ADDR(0x08)] = 0xb8;
				decoder->reg[REG_ADDR(0x12)] = 0xc9;
				decoder->reg[REG_ADDR(0x13)] = 0x80;
				decoder->reg[REG_ADDR(0x87)] = 0x01;
			} else {
				decoder->reg[REG_ADDR(0x08)] = 0x7c;
				decoder->reg[REG_ADDR(0x12)] = 0x00;
				decoder->reg[REG_ADDR(0x13)] = 0x00;
				decoder->reg[REG_ADDR(0x87)] = 0x00;
			}

			saa7114_write_block(client,
					    decoder->reg + (0x12 << 1),
					    2 << 1);
			saa7114_write(client, 0x08,
				      decoder->reg[REG_ADDR(0x08)]);
			saa7114_write(client, 0x87,
				      decoder->reg[REG_ADDR(0x87)]);
			saa7114_write(client, 0x88, 0xd8);	// sw reset scaler
			saa7114_write(client, 0x88, 0xf8);	// sw reset scaler release            
			saa7114_write(client, 0x80, 0x36);

		}
	}
		break;

	case DECODER_SET_PICTURE:
	{
		struct video_picture *pic = arg;

		dprintk(1,
			KERN_DEBUG
			"%s: decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n",
			I2C_NAME(client), pic->brightness, pic->contrast,
			pic->colour, pic->hue);

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