162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci    I2C functions
462306a36Sopenharmony_ci    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
562306a36Sopenharmony_ci    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/*
1062306a36Sopenharmony_ci    This file includes an i2c implementation that was reverse engineered
1162306a36Sopenharmony_ci    from the Hauppauge windows driver.  Older ivtv versions used i2c-algo-bit,
1262306a36Sopenharmony_ci    which whilst fine under most circumstances, had trouble with the Zilog
1362306a36Sopenharmony_ci    CPU on the PVR-150 which handles IR functions (occasional inability to
1462306a36Sopenharmony_ci    communicate with the chip until it was reset) and also with the i2c
1562306a36Sopenharmony_ci    bus being completely unreachable when multiple PVR cards were present.
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci    The implementation is very similar to i2c-algo-bit, but there are enough
1862306a36Sopenharmony_ci    subtle differences that the two are hard to merge.  The general strategy
1962306a36Sopenharmony_ci    employed by i2c-algo-bit is to use udelay() to implement the timing
2062306a36Sopenharmony_ci    when putting out bits on the scl/sda lines.  The general strategy taken
2162306a36Sopenharmony_ci    here is to poll the lines for state changes (see ivtv_waitscl and
2262306a36Sopenharmony_ci    ivtv_waitsda).  In addition there are small delays at various locations
2362306a36Sopenharmony_ci    which poll the SCL line 5 times (ivtv_scldelay).  I would guess that
2462306a36Sopenharmony_ci    since this is memory mapped I/O that the length of those delays is tied
2562306a36Sopenharmony_ci    to the PCI bus clock.  There is some extra code to do with recovery
2662306a36Sopenharmony_ci    and retries.  Since it is not known what causes the actual i2c problems
2762306a36Sopenharmony_ci    in the first place, the only goal if one was to attempt to use
2862306a36Sopenharmony_ci    i2c-algo-bit would be to try to make it follow the same code path.
2962306a36Sopenharmony_ci    This would be a lot of work, and I'm also not convinced that it would
3062306a36Sopenharmony_ci    provide a generic benefit to i2c-algo-bit.  Therefore consider this
3162306a36Sopenharmony_ci    an engineering solution -- not pretty, but it works.
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci    Some more general comments about what we are doing:
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci    The i2c bus is a 2 wire serial bus, with clock (SCL) and data (SDA)
3662306a36Sopenharmony_ci    lines.  To communicate on the bus (as a master, we don't act as a slave),
3762306a36Sopenharmony_ci    we first initiate a start condition (ivtv_start).  We then write the
3862306a36Sopenharmony_ci    address of the device that we want to communicate with, along with a flag
3962306a36Sopenharmony_ci    that indicates whether this is a read or a write.  The slave then issues
4062306a36Sopenharmony_ci    an ACK signal (ivtv_ack), which tells us that it is ready for reading /
4162306a36Sopenharmony_ci    writing.  We then proceed with reading or writing (ivtv_read/ivtv_write),
4262306a36Sopenharmony_ci    and finally issue a stop condition (ivtv_stop) to make the bus available
4362306a36Sopenharmony_ci    to other masters.
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci    There is an additional form of transaction where a write may be
4662306a36Sopenharmony_ci    immediately followed by a read.  In this case, there is no intervening
4762306a36Sopenharmony_ci    stop condition.  (Only the msp3400 chip uses this method of data transfer).
4862306a36Sopenharmony_ci */
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#include "ivtv-driver.h"
5162306a36Sopenharmony_ci#include "ivtv-cards.h"
5262306a36Sopenharmony_ci#include "ivtv-gpio.h"
5362306a36Sopenharmony_ci#include "ivtv-i2c.h"
5462306a36Sopenharmony_ci#include <media/drv-intf/cx25840.h>
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/* i2c implementation for cx23415/6 chip, ivtv project.
5762306a36Sopenharmony_ci * Author: Kevin Thayer (nufan_wfk at yahoo.com)
5862306a36Sopenharmony_ci */
5962306a36Sopenharmony_ci/* i2c stuff */
6062306a36Sopenharmony_ci#define IVTV_REG_I2C_SETSCL_OFFSET 0x7000
6162306a36Sopenharmony_ci#define IVTV_REG_I2C_SETSDA_OFFSET 0x7004
6262306a36Sopenharmony_ci#define IVTV_REG_I2C_GETSCL_OFFSET 0x7008
6362306a36Sopenharmony_ci#define IVTV_REG_I2C_GETSDA_OFFSET 0x700c
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#define IVTV_CS53L32A_I2C_ADDR		0x11
6662306a36Sopenharmony_ci#define IVTV_M52790_I2C_ADDR		0x48
6762306a36Sopenharmony_ci#define IVTV_CX25840_I2C_ADDR		0x44
6862306a36Sopenharmony_ci#define IVTV_SAA7115_I2C_ADDR		0x21
6962306a36Sopenharmony_ci#define IVTV_SAA7127_I2C_ADDR		0x44
7062306a36Sopenharmony_ci#define IVTV_SAA717x_I2C_ADDR		0x21
7162306a36Sopenharmony_ci#define IVTV_MSP3400_I2C_ADDR		0x40
7262306a36Sopenharmony_ci#define IVTV_HAUPPAUGE_I2C_ADDR		0x50
7362306a36Sopenharmony_ci#define IVTV_WM8739_I2C_ADDR		0x1a
7462306a36Sopenharmony_ci#define IVTV_WM8775_I2C_ADDR		0x1b
7562306a36Sopenharmony_ci#define IVTV_TEA5767_I2C_ADDR		0x60
7662306a36Sopenharmony_ci#define IVTV_UPD64031A_I2C_ADDR		0x12
7762306a36Sopenharmony_ci#define IVTV_UPD64083_I2C_ADDR		0x5c
7862306a36Sopenharmony_ci#define IVTV_VP27SMPX_I2C_ADDR		0x5b
7962306a36Sopenharmony_ci#define IVTV_M52790_I2C_ADDR		0x48
8062306a36Sopenharmony_ci#define IVTV_AVERMEDIA_IR_RX_I2C_ADDR	0x40
8162306a36Sopenharmony_ci#define IVTV_HAUP_EXT_IR_RX_I2C_ADDR	0x1a
8262306a36Sopenharmony_ci#define IVTV_HAUP_INT_IR_RX_I2C_ADDR	0x18
8362306a36Sopenharmony_ci#define IVTV_Z8F0811_IR_TX_I2C_ADDR	0x70
8462306a36Sopenharmony_ci#define IVTV_Z8F0811_IR_RX_I2C_ADDR	0x71
8562306a36Sopenharmony_ci#define IVTV_ADAPTEC_IR_ADDR		0x6b
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/* This array should match the IVTV_HW_ defines */
8862306a36Sopenharmony_cistatic const u8 hw_addrs[IVTV_HW_MAX_BITS] = {
8962306a36Sopenharmony_ci	IVTV_CX25840_I2C_ADDR,
9062306a36Sopenharmony_ci	IVTV_SAA7115_I2C_ADDR,
9162306a36Sopenharmony_ci	IVTV_SAA7127_I2C_ADDR,
9262306a36Sopenharmony_ci	IVTV_MSP3400_I2C_ADDR,
9362306a36Sopenharmony_ci	0,
9462306a36Sopenharmony_ci	IVTV_WM8775_I2C_ADDR,
9562306a36Sopenharmony_ci	IVTV_CS53L32A_I2C_ADDR,
9662306a36Sopenharmony_ci	0,
9762306a36Sopenharmony_ci	IVTV_SAA7115_I2C_ADDR,
9862306a36Sopenharmony_ci	IVTV_UPD64031A_I2C_ADDR,
9962306a36Sopenharmony_ci	IVTV_UPD64083_I2C_ADDR,
10062306a36Sopenharmony_ci	IVTV_SAA717x_I2C_ADDR,
10162306a36Sopenharmony_ci	IVTV_WM8739_I2C_ADDR,
10262306a36Sopenharmony_ci	IVTV_VP27SMPX_I2C_ADDR,
10362306a36Sopenharmony_ci	IVTV_M52790_I2C_ADDR,
10462306a36Sopenharmony_ci	0,				/* IVTV_HW_GPIO dummy driver ID */
10562306a36Sopenharmony_ci	IVTV_AVERMEDIA_IR_RX_I2C_ADDR,	/* IVTV_HW_I2C_IR_RX_AVER */
10662306a36Sopenharmony_ci	IVTV_HAUP_EXT_IR_RX_I2C_ADDR,	/* IVTV_HW_I2C_IR_RX_HAUP_EXT */
10762306a36Sopenharmony_ci	IVTV_HAUP_INT_IR_RX_I2C_ADDR,	/* IVTV_HW_I2C_IR_RX_HAUP_INT */
10862306a36Sopenharmony_ci	IVTV_Z8F0811_IR_RX_I2C_ADDR,	/* IVTV_HW_Z8F0811_IR_HAUP */
10962306a36Sopenharmony_ci	IVTV_ADAPTEC_IR_ADDR,		/* IVTV_HW_I2C_IR_RX_ADAPTEC */
11062306a36Sopenharmony_ci};
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/* This array should match the IVTV_HW_ defines */
11362306a36Sopenharmony_cistatic const char * const hw_devicenames[IVTV_HW_MAX_BITS] = {
11462306a36Sopenharmony_ci	"cx25840",
11562306a36Sopenharmony_ci	"saa7115",
11662306a36Sopenharmony_ci	"saa7127_auto",	/* saa7127 or saa7129 */
11762306a36Sopenharmony_ci	"msp3400",
11862306a36Sopenharmony_ci	"tuner",
11962306a36Sopenharmony_ci	"wm8775",
12062306a36Sopenharmony_ci	"cs53l32a",
12162306a36Sopenharmony_ci	"tveeprom",
12262306a36Sopenharmony_ci	"saa7114",
12362306a36Sopenharmony_ci	"upd64031a",
12462306a36Sopenharmony_ci	"upd64083",
12562306a36Sopenharmony_ci	"saa717x",
12662306a36Sopenharmony_ci	"wm8739",
12762306a36Sopenharmony_ci	"vp27smpx",
12862306a36Sopenharmony_ci	"m52790",
12962306a36Sopenharmony_ci	"gpio",
13062306a36Sopenharmony_ci	"ir_video",		/* IVTV_HW_I2C_IR_RX_AVER */
13162306a36Sopenharmony_ci	"ir_video",		/* IVTV_HW_I2C_IR_RX_HAUP_EXT */
13262306a36Sopenharmony_ci	"ir_video",		/* IVTV_HW_I2C_IR_RX_HAUP_INT */
13362306a36Sopenharmony_ci	"ir_z8f0811_haup",	/* IVTV_HW_Z8F0811_IR_HAUP */
13462306a36Sopenharmony_ci	"ir_video",		/* IVTV_HW_I2C_IR_RX_ADAPTEC */
13562306a36Sopenharmony_ci};
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic int get_key_adaptec(struct IR_i2c *ir, enum rc_proto *protocol,
13862306a36Sopenharmony_ci			   u32 *scancode, u8 *toggle)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	unsigned char keybuf[4];
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	keybuf[0] = 0x00;
14362306a36Sopenharmony_ci	i2c_master_send(ir->c, keybuf, 1);
14462306a36Sopenharmony_ci	/* poll IR chip */
14562306a36Sopenharmony_ci	if (i2c_master_recv(ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) {
14662306a36Sopenharmony_ci		return 0;
14762306a36Sopenharmony_ci	}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	/* key pressed ? */
15062306a36Sopenharmony_ci	if (keybuf[2] == 0xff)
15162306a36Sopenharmony_ci		return 0;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	/* remove repeat bit */
15462306a36Sopenharmony_ci	keybuf[2] &= 0x7f;
15562306a36Sopenharmony_ci	keybuf[3] |= 0x80;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	*protocol = RC_PROTO_UNKNOWN;
15862306a36Sopenharmony_ci	*scancode = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
15962306a36Sopenharmony_ci	*toggle = 0;
16062306a36Sopenharmony_ci	return 1;
16162306a36Sopenharmony_ci}
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_cistatic int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	struct i2c_board_info info;
16662306a36Sopenharmony_ci	struct i2c_adapter *adap = &itv->i2c_adap;
16762306a36Sopenharmony_ci	struct IR_i2c_init_data *init_data = &itv->ir_i2c_init_data;
16862306a36Sopenharmony_ci	unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	/* Only allow one IR receiver to be registered per board */
17162306a36Sopenharmony_ci	if (itv->hw_flags & IVTV_HW_IR_ANY)
17262306a36Sopenharmony_ci		return -1;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	/* Our default information for ir-kbd-i2c.c to use */
17562306a36Sopenharmony_ci	switch (hw) {
17662306a36Sopenharmony_ci	case IVTV_HW_I2C_IR_RX_AVER:
17762306a36Sopenharmony_ci		init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS;
17862306a36Sopenharmony_ci		init_data->internal_get_key_func =
17962306a36Sopenharmony_ci					IR_KBD_GET_KEY_AVERMEDIA_CARDBUS;
18062306a36Sopenharmony_ci		init_data->type = RC_PROTO_BIT_OTHER;
18162306a36Sopenharmony_ci		init_data->name = "AVerMedia AVerTV card";
18262306a36Sopenharmony_ci		break;
18362306a36Sopenharmony_ci	case IVTV_HW_I2C_IR_RX_HAUP_EXT:
18462306a36Sopenharmony_ci	case IVTV_HW_I2C_IR_RX_HAUP_INT:
18562306a36Sopenharmony_ci		init_data->ir_codes = RC_MAP_HAUPPAUGE;
18662306a36Sopenharmony_ci		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
18762306a36Sopenharmony_ci		init_data->type = RC_PROTO_BIT_RC5;
18862306a36Sopenharmony_ci		init_data->name = itv->card_name;
18962306a36Sopenharmony_ci		break;
19062306a36Sopenharmony_ci	case IVTV_HW_Z8F0811_IR_HAUP:
19162306a36Sopenharmony_ci		/* Default to grey remote */
19262306a36Sopenharmony_ci		init_data->ir_codes = RC_MAP_HAUPPAUGE;
19362306a36Sopenharmony_ci		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
19462306a36Sopenharmony_ci		init_data->type = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE |
19562306a36Sopenharmony_ci							RC_PROTO_BIT_RC6_6A_32;
19662306a36Sopenharmony_ci		init_data->name = itv->card_name;
19762306a36Sopenharmony_ci		break;
19862306a36Sopenharmony_ci	case IVTV_HW_I2C_IR_RX_ADAPTEC:
19962306a36Sopenharmony_ci		init_data->get_key = get_key_adaptec;
20062306a36Sopenharmony_ci		init_data->name = itv->card_name;
20162306a36Sopenharmony_ci		/* FIXME: The protocol and RC_MAP needs to be corrected */
20262306a36Sopenharmony_ci		init_data->ir_codes = RC_MAP_EMPTY;
20362306a36Sopenharmony_ci		init_data->type = RC_PROTO_BIT_UNKNOWN;
20462306a36Sopenharmony_ci		break;
20562306a36Sopenharmony_ci	}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	memset(&info, 0, sizeof(struct i2c_board_info));
20862306a36Sopenharmony_ci	info.platform_data = init_data;
20962306a36Sopenharmony_ci	strscpy(info.type, type, I2C_NAME_SIZE);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	return IS_ERR(i2c_new_scanned_device(adap, &info, addr_list, NULL)) ?
21262306a36Sopenharmony_ci	       -1 : 0;
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci/* Instantiate the IR receiver device using probing -- undesirable */
21662306a36Sopenharmony_civoid ivtv_i2c_new_ir_legacy(struct ivtv *itv)
21762306a36Sopenharmony_ci{
21862306a36Sopenharmony_ci	struct i2c_board_info info;
21962306a36Sopenharmony_ci	/*
22062306a36Sopenharmony_ci	 * The external IR receiver is at i2c address 0x34.
22162306a36Sopenharmony_ci	 * The internal IR receiver is at i2c address 0x30.
22262306a36Sopenharmony_ci	 *
22362306a36Sopenharmony_ci	 * In theory, both can be fitted, and Hauppauge suggests an external
22462306a36Sopenharmony_ci	 * overrides an internal.  That's why we probe 0x1a (~0x34) first. CB
22562306a36Sopenharmony_ci	 *
22662306a36Sopenharmony_ci	 * Some of these addresses we probe may collide with other i2c address
22762306a36Sopenharmony_ci	 * allocations, so this function must be called after all other i2c
22862306a36Sopenharmony_ci	 * devices we care about are registered.
22962306a36Sopenharmony_ci	 */
23062306a36Sopenharmony_ci	static const unsigned short addr_list[] = {
23162306a36Sopenharmony_ci		0x1a,	/* Hauppauge IR external - collides with WM8739 */
23262306a36Sopenharmony_ci		0x18,	/* Hauppauge IR internal */
23362306a36Sopenharmony_ci		I2C_CLIENT_END
23462306a36Sopenharmony_ci	};
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	memset(&info, 0, sizeof(struct i2c_board_info));
23762306a36Sopenharmony_ci	strscpy(info.type, "ir_video", I2C_NAME_SIZE);
23862306a36Sopenharmony_ci	i2c_new_scanned_device(&itv->i2c_adap, &info, addr_list, NULL);
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ciint ivtv_i2c_register(struct ivtv *itv, unsigned idx)
24262306a36Sopenharmony_ci{
24362306a36Sopenharmony_ci	struct i2c_adapter *adap = &itv->i2c_adap;
24462306a36Sopenharmony_ci	struct v4l2_subdev *sd;
24562306a36Sopenharmony_ci	const char *type;
24662306a36Sopenharmony_ci	u32 hw;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	if (idx >= IVTV_HW_MAX_BITS)
24962306a36Sopenharmony_ci		return -ENODEV;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	type = hw_devicenames[idx];
25262306a36Sopenharmony_ci	hw = 1 << idx;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	if (hw == IVTV_HW_TUNER) {
25562306a36Sopenharmony_ci		/* special tuner handling */
25662306a36Sopenharmony_ci		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
25762306a36Sopenharmony_ci				itv->card_i2c->radio);
25862306a36Sopenharmony_ci		if (sd)
25962306a36Sopenharmony_ci			sd->grp_id = 1 << idx;
26062306a36Sopenharmony_ci		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
26162306a36Sopenharmony_ci				itv->card_i2c->demod);
26262306a36Sopenharmony_ci		if (sd)
26362306a36Sopenharmony_ci			sd->grp_id = 1 << idx;
26462306a36Sopenharmony_ci		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
26562306a36Sopenharmony_ci				itv->card_i2c->tv);
26662306a36Sopenharmony_ci		if (sd)
26762306a36Sopenharmony_ci			sd->grp_id = 1 << idx;
26862306a36Sopenharmony_ci		return sd ? 0 : -1;
26962306a36Sopenharmony_ci	}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	if (hw & IVTV_HW_IR_ANY)
27262306a36Sopenharmony_ci		return ivtv_i2c_new_ir(itv, hw, type, hw_addrs[idx]);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	/* Is it not an I2C device or one we do not wish to register? */
27562306a36Sopenharmony_ci	if (!hw_addrs[idx])
27662306a36Sopenharmony_ci		return -1;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	/* It's an I2C device other than an analog tuner or IR chip */
27962306a36Sopenharmony_ci	if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) {
28062306a36Sopenharmony_ci		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
28162306a36Sopenharmony_ci				adap, type, 0, I2C_ADDRS(hw_addrs[idx]));
28262306a36Sopenharmony_ci	} else if (hw == IVTV_HW_CX25840) {
28362306a36Sopenharmony_ci		struct cx25840_platform_data pdata;
28462306a36Sopenharmony_ci		struct i2c_board_info cx25840_info = {
28562306a36Sopenharmony_ci			.type = "cx25840",
28662306a36Sopenharmony_ci			.addr = hw_addrs[idx],
28762306a36Sopenharmony_ci			.platform_data = &pdata,
28862306a36Sopenharmony_ci		};
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci		memset(&pdata, 0, sizeof(pdata));
29162306a36Sopenharmony_ci		pdata.pvr150_workaround = itv->pvr150_workaround;
29262306a36Sopenharmony_ci		sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap,
29362306a36Sopenharmony_ci				&cx25840_info, NULL);
29462306a36Sopenharmony_ci	} else {
29562306a36Sopenharmony_ci		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
29662306a36Sopenharmony_ci				adap, type, hw_addrs[idx], NULL);
29762306a36Sopenharmony_ci	}
29862306a36Sopenharmony_ci	if (sd)
29962306a36Sopenharmony_ci		sd->grp_id = 1 << idx;
30062306a36Sopenharmony_ci	return sd ? 0 : -1;
30162306a36Sopenharmony_ci}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_cistruct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw)
30462306a36Sopenharmony_ci{
30562306a36Sopenharmony_ci	struct v4l2_subdev *result = NULL;
30662306a36Sopenharmony_ci	struct v4l2_subdev *sd;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	spin_lock(&itv->v4l2_dev.lock);
30962306a36Sopenharmony_ci	v4l2_device_for_each_subdev(sd, &itv->v4l2_dev) {
31062306a36Sopenharmony_ci		if (sd->grp_id == hw) {
31162306a36Sopenharmony_ci			result = sd;
31262306a36Sopenharmony_ci			break;
31362306a36Sopenharmony_ci		}
31462306a36Sopenharmony_ci	}
31562306a36Sopenharmony_ci	spin_unlock(&itv->v4l2_dev.lock);
31662306a36Sopenharmony_ci	return result;
31762306a36Sopenharmony_ci}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci/* Set the serial clock line to the desired state */
32062306a36Sopenharmony_cistatic void ivtv_setscl(struct ivtv *itv, int state)
32162306a36Sopenharmony_ci{
32262306a36Sopenharmony_ci	/* write them out */
32362306a36Sopenharmony_ci	/* write bits are inverted */
32462306a36Sopenharmony_ci	write_reg(~state, IVTV_REG_I2C_SETSCL_OFFSET);
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci/* Set the serial data line to the desired state */
32862306a36Sopenharmony_cistatic void ivtv_setsda(struct ivtv *itv, int state)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	/* write them out */
33162306a36Sopenharmony_ci	/* write bits are inverted */
33262306a36Sopenharmony_ci	write_reg(~state & 1, IVTV_REG_I2C_SETSDA_OFFSET);
33362306a36Sopenharmony_ci}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci/* Read the serial clock line */
33662306a36Sopenharmony_cistatic int ivtv_getscl(struct ivtv *itv)
33762306a36Sopenharmony_ci{
33862306a36Sopenharmony_ci	return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1;
33962306a36Sopenharmony_ci}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci/* Read the serial data line */
34262306a36Sopenharmony_cistatic int ivtv_getsda(struct ivtv *itv)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1;
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci/* Implement a short delay by polling the serial clock line */
34862306a36Sopenharmony_cistatic void ivtv_scldelay(struct ivtv *itv)
34962306a36Sopenharmony_ci{
35062306a36Sopenharmony_ci	int i;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	for (i = 0; i < 5; ++i)
35362306a36Sopenharmony_ci		ivtv_getscl(itv);
35462306a36Sopenharmony_ci}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci/* Wait for the serial clock line to become set to a specific value */
35762306a36Sopenharmony_cistatic int ivtv_waitscl(struct ivtv *itv, int val)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	int i;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	ivtv_scldelay(itv);
36262306a36Sopenharmony_ci	for (i = 0; i < 1000; ++i) {
36362306a36Sopenharmony_ci		if (ivtv_getscl(itv) == val)
36462306a36Sopenharmony_ci			return 1;
36562306a36Sopenharmony_ci	}
36662306a36Sopenharmony_ci	return 0;
36762306a36Sopenharmony_ci}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci/* Wait for the serial data line to become set to a specific value */
37062306a36Sopenharmony_cistatic int ivtv_waitsda(struct ivtv *itv, int val)
37162306a36Sopenharmony_ci{
37262306a36Sopenharmony_ci	int i;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	ivtv_scldelay(itv);
37562306a36Sopenharmony_ci	for (i = 0; i < 1000; ++i) {
37662306a36Sopenharmony_ci		if (ivtv_getsda(itv) == val)
37762306a36Sopenharmony_ci			return 1;
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci	return 0;
38062306a36Sopenharmony_ci}
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci/* Wait for the slave to issue an ACK */
38362306a36Sopenharmony_cistatic int ivtv_ack(struct ivtv *itv)
38462306a36Sopenharmony_ci{
38562306a36Sopenharmony_ci	int ret = 0;
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	if (ivtv_getscl(itv) == 1) {
38862306a36Sopenharmony_ci		IVTV_DEBUG_HI_I2C("SCL was high starting an ack\n");
38962306a36Sopenharmony_ci		ivtv_setscl(itv, 0);
39062306a36Sopenharmony_ci		if (!ivtv_waitscl(itv, 0)) {
39162306a36Sopenharmony_ci			IVTV_DEBUG_I2C("Could not set SCL low starting an ack\n");
39262306a36Sopenharmony_ci			return -EREMOTEIO;
39362306a36Sopenharmony_ci		}
39462306a36Sopenharmony_ci	}
39562306a36Sopenharmony_ci	ivtv_setsda(itv, 1);
39662306a36Sopenharmony_ci	ivtv_scldelay(itv);
39762306a36Sopenharmony_ci	ivtv_setscl(itv, 1);
39862306a36Sopenharmony_ci	if (!ivtv_waitsda(itv, 0)) {
39962306a36Sopenharmony_ci		IVTV_DEBUG_I2C("Slave did not ack\n");
40062306a36Sopenharmony_ci		ret = -EREMOTEIO;
40162306a36Sopenharmony_ci	}
40262306a36Sopenharmony_ci	ivtv_setscl(itv, 0);
40362306a36Sopenharmony_ci	if (!ivtv_waitscl(itv, 0)) {
40462306a36Sopenharmony_ci		IVTV_DEBUG_I2C("Failed to set SCL low after ACK\n");
40562306a36Sopenharmony_ci		ret = -EREMOTEIO;
40662306a36Sopenharmony_ci	}
40762306a36Sopenharmony_ci	return ret;
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci/* Write a single byte to the i2c bus and wait for the slave to ACK */
41162306a36Sopenharmony_cistatic int ivtv_sendbyte(struct ivtv *itv, unsigned char byte)
41262306a36Sopenharmony_ci{
41362306a36Sopenharmony_ci	int i, bit;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	IVTV_DEBUG_HI_I2C("write %x\n",byte);
41662306a36Sopenharmony_ci	for (i = 0; i < 8; ++i, byte<<=1) {
41762306a36Sopenharmony_ci		ivtv_setscl(itv, 0);
41862306a36Sopenharmony_ci		if (!ivtv_waitscl(itv, 0)) {
41962306a36Sopenharmony_ci			IVTV_DEBUG_I2C("Error setting SCL low\n");
42062306a36Sopenharmony_ci			return -EREMOTEIO;
42162306a36Sopenharmony_ci		}
42262306a36Sopenharmony_ci		bit = (byte>>7)&1;
42362306a36Sopenharmony_ci		ivtv_setsda(itv, bit);
42462306a36Sopenharmony_ci		if (!ivtv_waitsda(itv, bit)) {
42562306a36Sopenharmony_ci			IVTV_DEBUG_I2C("Error setting SDA\n");
42662306a36Sopenharmony_ci			return -EREMOTEIO;
42762306a36Sopenharmony_ci		}
42862306a36Sopenharmony_ci		ivtv_setscl(itv, 1);
42962306a36Sopenharmony_ci		if (!ivtv_waitscl(itv, 1)) {
43062306a36Sopenharmony_ci			IVTV_DEBUG_I2C("Slave not ready for bit\n");
43162306a36Sopenharmony_ci			return -EREMOTEIO;
43262306a36Sopenharmony_ci		}
43362306a36Sopenharmony_ci	}
43462306a36Sopenharmony_ci	ivtv_setscl(itv, 0);
43562306a36Sopenharmony_ci	if (!ivtv_waitscl(itv, 0)) {
43662306a36Sopenharmony_ci		IVTV_DEBUG_I2C("Error setting SCL low\n");
43762306a36Sopenharmony_ci		return -EREMOTEIO;
43862306a36Sopenharmony_ci	}
43962306a36Sopenharmony_ci	return ivtv_ack(itv);
44062306a36Sopenharmony_ci}
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci/* Read a byte from the i2c bus and send a NACK if applicable (i.e. for the
44362306a36Sopenharmony_ci   final byte) */
44462306a36Sopenharmony_cistatic int ivtv_readbyte(struct ivtv *itv, unsigned char *byte, int nack)
44562306a36Sopenharmony_ci{
44662306a36Sopenharmony_ci	int i;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	*byte = 0;
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	ivtv_setsda(itv, 1);
45162306a36Sopenharmony_ci	ivtv_scldelay(itv);
45262306a36Sopenharmony_ci	for (i = 0; i < 8; ++i) {
45362306a36Sopenharmony_ci		ivtv_setscl(itv, 0);
45462306a36Sopenharmony_ci		ivtv_scldelay(itv);
45562306a36Sopenharmony_ci		ivtv_setscl(itv, 1);
45662306a36Sopenharmony_ci		if (!ivtv_waitscl(itv, 1)) {
45762306a36Sopenharmony_ci			IVTV_DEBUG_I2C("Error setting SCL high\n");
45862306a36Sopenharmony_ci			return -EREMOTEIO;
45962306a36Sopenharmony_ci		}
46062306a36Sopenharmony_ci		*byte = ((*byte)<<1)|ivtv_getsda(itv);
46162306a36Sopenharmony_ci	}
46262306a36Sopenharmony_ci	ivtv_setscl(itv, 0);
46362306a36Sopenharmony_ci	ivtv_scldelay(itv);
46462306a36Sopenharmony_ci	ivtv_setsda(itv, nack);
46562306a36Sopenharmony_ci	ivtv_scldelay(itv);
46662306a36Sopenharmony_ci	ivtv_setscl(itv, 1);
46762306a36Sopenharmony_ci	ivtv_scldelay(itv);
46862306a36Sopenharmony_ci	ivtv_setscl(itv, 0);
46962306a36Sopenharmony_ci	ivtv_scldelay(itv);
47062306a36Sopenharmony_ci	IVTV_DEBUG_HI_I2C("read %x\n",*byte);
47162306a36Sopenharmony_ci	return 0;
47262306a36Sopenharmony_ci}
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci/* Issue a start condition on the i2c bus to alert slaves to prepare for
47562306a36Sopenharmony_ci   an address write */
47662306a36Sopenharmony_cistatic int ivtv_start(struct ivtv *itv)
47762306a36Sopenharmony_ci{
47862306a36Sopenharmony_ci	int sda;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	sda = ivtv_getsda(itv);
48162306a36Sopenharmony_ci	if (sda != 1) {
48262306a36Sopenharmony_ci		IVTV_DEBUG_HI_I2C("SDA was low at start\n");
48362306a36Sopenharmony_ci		ivtv_setsda(itv, 1);
48462306a36Sopenharmony_ci		if (!ivtv_waitsda(itv, 1)) {
48562306a36Sopenharmony_ci			IVTV_DEBUG_I2C("SDA stuck low\n");
48662306a36Sopenharmony_ci			return -EREMOTEIO;
48762306a36Sopenharmony_ci		}
48862306a36Sopenharmony_ci	}
48962306a36Sopenharmony_ci	if (ivtv_getscl(itv) != 1) {
49062306a36Sopenharmony_ci		ivtv_setscl(itv, 1);
49162306a36Sopenharmony_ci		if (!ivtv_waitscl(itv, 1)) {
49262306a36Sopenharmony_ci			IVTV_DEBUG_I2C("SCL stuck low at start\n");
49362306a36Sopenharmony_ci			return -EREMOTEIO;
49462306a36Sopenharmony_ci		}
49562306a36Sopenharmony_ci	}
49662306a36Sopenharmony_ci	ivtv_setsda(itv, 0);
49762306a36Sopenharmony_ci	ivtv_scldelay(itv);
49862306a36Sopenharmony_ci	return 0;
49962306a36Sopenharmony_ci}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci/* Issue a stop condition on the i2c bus to release it */
50262306a36Sopenharmony_cistatic int ivtv_stop(struct ivtv *itv)
50362306a36Sopenharmony_ci{
50462306a36Sopenharmony_ci	int i;
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	if (ivtv_getscl(itv) != 0) {
50762306a36Sopenharmony_ci		IVTV_DEBUG_HI_I2C("SCL not low when stopping\n");
50862306a36Sopenharmony_ci		ivtv_setscl(itv, 0);
50962306a36Sopenharmony_ci		if (!ivtv_waitscl(itv, 0)) {
51062306a36Sopenharmony_ci			IVTV_DEBUG_I2C("SCL could not be set low\n");
51162306a36Sopenharmony_ci		}
51262306a36Sopenharmony_ci	}
51362306a36Sopenharmony_ci	ivtv_setsda(itv, 0);
51462306a36Sopenharmony_ci	ivtv_scldelay(itv);
51562306a36Sopenharmony_ci	ivtv_setscl(itv, 1);
51662306a36Sopenharmony_ci	if (!ivtv_waitscl(itv, 1)) {
51762306a36Sopenharmony_ci		IVTV_DEBUG_I2C("SCL could not be set high\n");
51862306a36Sopenharmony_ci		return -EREMOTEIO;
51962306a36Sopenharmony_ci	}
52062306a36Sopenharmony_ci	ivtv_scldelay(itv);
52162306a36Sopenharmony_ci	ivtv_setsda(itv, 1);
52262306a36Sopenharmony_ci	if (!ivtv_waitsda(itv, 1)) {
52362306a36Sopenharmony_ci		IVTV_DEBUG_I2C("resetting I2C\n");
52462306a36Sopenharmony_ci		for (i = 0; i < 16; ++i) {
52562306a36Sopenharmony_ci			ivtv_setscl(itv, 0);
52662306a36Sopenharmony_ci			ivtv_scldelay(itv);
52762306a36Sopenharmony_ci			ivtv_setscl(itv, 1);
52862306a36Sopenharmony_ci			ivtv_scldelay(itv);
52962306a36Sopenharmony_ci			ivtv_setsda(itv, 1);
53062306a36Sopenharmony_ci		}
53162306a36Sopenharmony_ci		ivtv_waitsda(itv, 1);
53262306a36Sopenharmony_ci		return -EREMOTEIO;
53362306a36Sopenharmony_ci	}
53462306a36Sopenharmony_ci	return 0;
53562306a36Sopenharmony_ci}
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci/* Write a message to the given i2c slave.  do_stop may be 0 to prevent
53862306a36Sopenharmony_ci   issuing the i2c stop condition (when following with a read) */
53962306a36Sopenharmony_cistatic int ivtv_write(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len, int do_stop)
54062306a36Sopenharmony_ci{
54162306a36Sopenharmony_ci	int retry, ret = -EREMOTEIO;
54262306a36Sopenharmony_ci	u32 i;
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	for (retry = 0; ret != 0 && retry < 8; ++retry) {
54562306a36Sopenharmony_ci		ret = ivtv_start(itv);
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci		if (ret == 0) {
54862306a36Sopenharmony_ci			ret = ivtv_sendbyte(itv, addr<<1);
54962306a36Sopenharmony_ci			for (i = 0; ret == 0 && i < len; ++i)
55062306a36Sopenharmony_ci				ret = ivtv_sendbyte(itv, data[i]);
55162306a36Sopenharmony_ci		}
55262306a36Sopenharmony_ci		if (ret != 0 || do_stop) {
55362306a36Sopenharmony_ci			ivtv_stop(itv);
55462306a36Sopenharmony_ci		}
55562306a36Sopenharmony_ci	}
55662306a36Sopenharmony_ci	if (ret)
55762306a36Sopenharmony_ci		IVTV_DEBUG_I2C("i2c write to %x failed\n", addr);
55862306a36Sopenharmony_ci	return ret;
55962306a36Sopenharmony_ci}
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci/* Read data from the given i2c slave.  A stop condition is always issued. */
56262306a36Sopenharmony_cistatic int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len)
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	int retry, ret = -EREMOTEIO;
56562306a36Sopenharmony_ci	u32 i;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	for (retry = 0; ret != 0 && retry < 8; ++retry) {
56862306a36Sopenharmony_ci		ret = ivtv_start(itv);
56962306a36Sopenharmony_ci		if (ret == 0)
57062306a36Sopenharmony_ci			ret = ivtv_sendbyte(itv, (addr << 1) | 1);
57162306a36Sopenharmony_ci		for (i = 0; ret == 0 && i < len; ++i) {
57262306a36Sopenharmony_ci			ret = ivtv_readbyte(itv, &data[i], i == len - 1);
57362306a36Sopenharmony_ci		}
57462306a36Sopenharmony_ci		ivtv_stop(itv);
57562306a36Sopenharmony_ci	}
57662306a36Sopenharmony_ci	if (ret)
57762306a36Sopenharmony_ci		IVTV_DEBUG_I2C("i2c read from %x failed\n", addr);
57862306a36Sopenharmony_ci	return ret;
57962306a36Sopenharmony_ci}
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci/* Kernel i2c transfer implementation.  Takes a number of messages to be read
58262306a36Sopenharmony_ci   or written.  If a read follows a write, this will occur without an
58362306a36Sopenharmony_ci   intervening stop condition */
58462306a36Sopenharmony_cistatic int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
58562306a36Sopenharmony_ci{
58662306a36Sopenharmony_ci	struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
58762306a36Sopenharmony_ci	struct ivtv *itv = to_ivtv(v4l2_dev);
58862306a36Sopenharmony_ci	int retval;
58962306a36Sopenharmony_ci	int i;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	mutex_lock(&itv->i2c_bus_lock);
59262306a36Sopenharmony_ci	for (i = retval = 0; retval == 0 && i < num; i++) {
59362306a36Sopenharmony_ci		if (msgs[i].flags & I2C_M_RD)
59462306a36Sopenharmony_ci			retval = ivtv_read(itv, msgs[i].addr, msgs[i].buf, msgs[i].len);
59562306a36Sopenharmony_ci		else {
59662306a36Sopenharmony_ci			/* if followed by a read, don't stop */
59762306a36Sopenharmony_ci			int stop = !(i + 1 < num && msgs[i + 1].flags == I2C_M_RD);
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci			retval = ivtv_write(itv, msgs[i].addr, msgs[i].buf, msgs[i].len, stop);
60062306a36Sopenharmony_ci		}
60162306a36Sopenharmony_ci	}
60262306a36Sopenharmony_ci	mutex_unlock(&itv->i2c_bus_lock);
60362306a36Sopenharmony_ci	return retval ? retval : num;
60462306a36Sopenharmony_ci}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci/* Kernel i2c capabilities */
60762306a36Sopenharmony_cistatic u32 ivtv_functionality(struct i2c_adapter *adap)
60862306a36Sopenharmony_ci{
60962306a36Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_cistatic const struct i2c_algorithm ivtv_algo = {
61362306a36Sopenharmony_ci	.master_xfer   = ivtv_xfer,
61462306a36Sopenharmony_ci	.functionality = ivtv_functionality,
61562306a36Sopenharmony_ci};
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci/* template for our-bit banger */
61862306a36Sopenharmony_cistatic const struct i2c_adapter ivtv_i2c_adap_hw_template = {
61962306a36Sopenharmony_ci	.name = "ivtv i2c driver",
62062306a36Sopenharmony_ci	.algo = &ivtv_algo,
62162306a36Sopenharmony_ci	.algo_data = NULL,			/* filled from template */
62262306a36Sopenharmony_ci	.owner = THIS_MODULE,
62362306a36Sopenharmony_ci};
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_cistatic void ivtv_setscl_old(void *data, int state)
62662306a36Sopenharmony_ci{
62762306a36Sopenharmony_ci	struct ivtv *itv = (struct ivtv *)data;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	if (state)
63062306a36Sopenharmony_ci		itv->i2c_state |= 0x01;
63162306a36Sopenharmony_ci	else
63262306a36Sopenharmony_ci		itv->i2c_state &= ~0x01;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	/* write them out */
63562306a36Sopenharmony_ci	/* write bits are inverted */
63662306a36Sopenharmony_ci	write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSCL_OFFSET);
63762306a36Sopenharmony_ci}
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_cistatic void ivtv_setsda_old(void *data, int state)
64062306a36Sopenharmony_ci{
64162306a36Sopenharmony_ci	struct ivtv *itv = (struct ivtv *)data;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	if (state)
64462306a36Sopenharmony_ci		itv->i2c_state |= 0x01;
64562306a36Sopenharmony_ci	else
64662306a36Sopenharmony_ci		itv->i2c_state &= ~0x01;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	/* write them out */
64962306a36Sopenharmony_ci	/* write bits are inverted */
65062306a36Sopenharmony_ci	write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSDA_OFFSET);
65162306a36Sopenharmony_ci}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_cistatic int ivtv_getscl_old(void *data)
65462306a36Sopenharmony_ci{
65562306a36Sopenharmony_ci	struct ivtv *itv = (struct ivtv *)data;
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1;
65862306a36Sopenharmony_ci}
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_cistatic int ivtv_getsda_old(void *data)
66162306a36Sopenharmony_ci{
66262306a36Sopenharmony_ci	struct ivtv *itv = (struct ivtv *)data;
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1;
66562306a36Sopenharmony_ci}
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci/* template for i2c-bit-algo */
66862306a36Sopenharmony_cistatic const struct i2c_adapter ivtv_i2c_adap_template = {
66962306a36Sopenharmony_ci	.name = "ivtv i2c driver",
67062306a36Sopenharmony_ci	.algo = NULL,                   /* set by i2c-algo-bit */
67162306a36Sopenharmony_ci	.algo_data = NULL,              /* filled from template */
67262306a36Sopenharmony_ci	.owner = THIS_MODULE,
67362306a36Sopenharmony_ci};
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci#define IVTV_ALGO_BIT_TIMEOUT	(2)	/* seconds */
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_cistatic const struct i2c_algo_bit_data ivtv_i2c_algo_template = {
67862306a36Sopenharmony_ci	.setsda		= ivtv_setsda_old,
67962306a36Sopenharmony_ci	.setscl		= ivtv_setscl_old,
68062306a36Sopenharmony_ci	.getsda		= ivtv_getsda_old,
68162306a36Sopenharmony_ci	.getscl		= ivtv_getscl_old,
68262306a36Sopenharmony_ci	.udelay		= IVTV_DEFAULT_I2C_CLOCK_PERIOD / 2,  /* microseconds */
68362306a36Sopenharmony_ci	.timeout	= IVTV_ALGO_BIT_TIMEOUT * HZ,         /* jiffies */
68462306a36Sopenharmony_ci};
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_cistatic const struct i2c_client ivtv_i2c_client_template = {
68762306a36Sopenharmony_ci	.name = "ivtv internal",
68862306a36Sopenharmony_ci};
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci/* init + register i2c adapter */
69162306a36Sopenharmony_ciint init_ivtv_i2c(struct ivtv *itv)
69262306a36Sopenharmony_ci{
69362306a36Sopenharmony_ci	int retval;
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	IVTV_DEBUG_I2C("i2c init\n");
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	/* Sanity checks for the I2C hardware arrays. They must be the
69862306a36Sopenharmony_ci	 * same size.
69962306a36Sopenharmony_ci	 */
70062306a36Sopenharmony_ci	if (ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs)) {
70162306a36Sopenharmony_ci		IVTV_ERR("Mismatched I2C hardware arrays\n");
70262306a36Sopenharmony_ci		return -ENODEV;
70362306a36Sopenharmony_ci	}
70462306a36Sopenharmony_ci	if (itv->options.newi2c > 0) {
70562306a36Sopenharmony_ci		itv->i2c_adap = ivtv_i2c_adap_hw_template;
70662306a36Sopenharmony_ci	} else {
70762306a36Sopenharmony_ci		itv->i2c_adap = ivtv_i2c_adap_template;
70862306a36Sopenharmony_ci		itv->i2c_algo = ivtv_i2c_algo_template;
70962306a36Sopenharmony_ci	}
71062306a36Sopenharmony_ci	itv->i2c_algo.udelay = itv->options.i2c_clock_period / 2;
71162306a36Sopenharmony_ci	itv->i2c_algo.data = itv;
71262306a36Sopenharmony_ci	itv->i2c_adap.algo_data = &itv->i2c_algo;
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d",
71562306a36Sopenharmony_ci		itv->instance);
71662306a36Sopenharmony_ci	i2c_set_adapdata(&itv->i2c_adap, &itv->v4l2_dev);
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	itv->i2c_client = ivtv_i2c_client_template;
71962306a36Sopenharmony_ci	itv->i2c_client.adapter = &itv->i2c_adap;
72062306a36Sopenharmony_ci	itv->i2c_adap.dev.parent = &itv->pdev->dev;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	IVTV_DEBUG_I2C("setting scl and sda to 1\n");
72362306a36Sopenharmony_ci	ivtv_setscl(itv, 1);
72462306a36Sopenharmony_ci	ivtv_setsda(itv, 1);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	if (itv->options.newi2c > 0)
72762306a36Sopenharmony_ci		retval = i2c_add_adapter(&itv->i2c_adap);
72862306a36Sopenharmony_ci	else
72962306a36Sopenharmony_ci		retval = i2c_bit_add_bus(&itv->i2c_adap);
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	return retval;
73262306a36Sopenharmony_ci}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_civoid exit_ivtv_i2c(struct ivtv *itv)
73562306a36Sopenharmony_ci{
73662306a36Sopenharmony_ci	IVTV_DEBUG_I2C("i2c exit\n");
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	i2c_del_adapter(&itv->i2c_adap);
73962306a36Sopenharmony_ci}
740