tea6415c.c 4.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4
 /*
    tea6415c - i2c-driver for the tea6415c by SGS Thomson

    Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
5
    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
L
Linus Torvalds 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

    The tea6415c is a bus controlled video-matrix-switch
    with 8 inputs and 6 outputs.
    It is cascadable, i.e. it can be found at the addresses
    0x86 and 0x06 on the i2c-bus.

    For detailed informations download the specifications directly
    from SGS Thomson at http://www.st.com

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License vs published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA.
  */

30

L
Linus Torvalds 已提交
31 32 33
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/i2c.h>
34
#include <media/v4l2-device.h>
35 36
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-i2c-drv.h>
L
Linus Torvalds 已提交
37 38
#include "tea6415c.h"

39 40 41
MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
MODULE_DESCRIPTION("tea6415c driver");
MODULE_LICENSE("GPL");
42

43 44
static int debug;
module_param(debug, int, 0644);
L
Linus Torvalds 已提交
45

46
MODULE_PARM_DESC(debug, "Debug level (0-1)");
L
Linus Torvalds 已提交
47 48


49 50
/* makes a connection between the input-pin 'i' and the output-pin 'o' */
static int tea6415c_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
L
Linus Torvalds 已提交
51
{
52
	struct i2c_client *client = v4l2_get_subdevdata(sd);
L
Linus Torvalds 已提交
53
	u8 byte = 0;
54 55
	u32 i = route->input;
	u32 o = route->output;
L
Linus Torvalds 已提交
56
	int ret;
57

58
	v4l2_dbg(1, debug, sd, "i=%d, o=%d\n", i, o);
L
Linus Torvalds 已提交
59 60 61 62

	/* check if the pins are valid */
	if (0 == ((1 == i ||  3 == i ||  5 == i ||  6 == i ||  8 == i || 10 == i || 20 == i || 11 == i)
	      && (18 == o || 17 == o || 16 == o || 15 == o || 14 == o || 13 == o)))
63
		return -EINVAL;
L
Linus Torvalds 已提交
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115

	/* to understand this, have a look at the tea6415c-specs (p.5) */
	switch (o) {
	case 18:
		byte = 0x00;
		break;
	case 14:
		byte = 0x20;
		break;
	case 16:
		byte = 0x10;
		break;
	case 17:
		byte = 0x08;
		break;
	case 15:
		byte = 0x18;
		break;
	case 13:
		byte = 0x28;
		break;
	};

	switch (i) {
	case 5:
		byte |= 0x00;
		break;
	case 8:
		byte |= 0x04;
		break;
	case 3:
		byte |= 0x02;
		break;
	case 20:
		byte |= 0x06;
		break;
	case 6:
		byte |= 0x01;
		break;
	case 10:
		byte |= 0x05;
		break;
	case 1:
		byte |= 0x03;
		break;
	case 11:
		byte |= 0x07;
		break;
	};

	ret = i2c_smbus_write_byte(client, byte);
	if (ret) {
116
		v4l2_dbg(1, debug, sd,
117
			"i2c_smbus_write_byte() failed, ret:%d\n", ret);
L
Linus Torvalds 已提交
118 119 120 121 122
		return -EIO;
	}
	return ret;
}

123
static int tea6415c_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
L
Linus Torvalds 已提交
124
{
125
	struct i2c_client *client = v4l2_get_subdevdata(sd);
L
Linus Torvalds 已提交
126

127
	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEA6415C, 0);
128 129 130 131 132
}

/* ----------------------------------------------------------------------- */

static const struct v4l2_subdev_core_ops tea6415c_core_ops = {
133 134 135 136 137
	.g_chip_ident = tea6415c_g_chip_ident,
};

static const struct v4l2_subdev_video_ops tea6415c_video_ops = {
	.s_routing = tea6415c_s_routing,
138 139 140 141
};

static const struct v4l2_subdev_ops tea6415c_ops = {
	.core = &tea6415c_core_ops,
142
	.video = &tea6415c_video_ops,
143 144
};

145 146 147
/* this function is called by i2c_probe */
static int tea6415c_probe(struct i2c_client *client,
			  const struct i2c_device_id *id)
L
Linus Torvalds 已提交
148
{
149 150
	struct v4l2_subdev *sd;

151 152 153 154 155 156
	/* let's see whether this adapter can support what we need */
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE))
		return 0;

	v4l_info(client, "chip found @ 0x%x (%s)\n",
			client->addr << 1, client->adapter->name);
157 158 159 160 161 162 163 164 165 166 167 168 169
	sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
	if (sd == NULL)
		return -ENOMEM;
	v4l2_i2c_subdev_init(sd, client, &tea6415c_ops);
	return 0;
}

static int tea6415c_remove(struct i2c_client *client)
{
	struct v4l2_subdev *sd = i2c_get_clientdata(client);

	v4l2_device_unregister_subdev(sd);
	kfree(sd);
170
	return 0;
L
Linus Torvalds 已提交
171 172
}

173 174 175 176 177
static const struct i2c_device_id tea6415c_id[] = {
	{ "tea6415c", 0 },
	{ }
};
MODULE_DEVICE_TABLE(i2c, tea6415c_id);
L
Linus Torvalds 已提交
178

179 180 181
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
	.name = "tea6415c",
	.probe = tea6415c_probe,
182
	.remove = tea6415c_remove,
183 184
	.id_table = tea6415c_id,
};