brintos

brintos / linux-shallow public Read only

0
0
Text · 8.5 KiB · a834352 Raw
310 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  cx18 I2C functions4 *5 *  Derived from ivtv-i2c.c6 *7 *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>8 *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>9 */10 11#include "cx18-driver.h"12#include "cx18-io.h"13#include "cx18-cards.h"14#include "cx18-gpio.h"15#include "cx18-i2c.h"16#include "cx18-irq.h"17 18#define CX18_REG_I2C_1_WR   0xf1500019#define CX18_REG_I2C_1_RD   0xf1500820#define CX18_REG_I2C_2_WR   0xf2510021#define CX18_REG_I2C_2_RD   0xf2510822 23#define SETSCL_BIT      0x000124#define SETSDL_BIT      0x000225#define GETSCL_BIT      0x000426#define GETSDL_BIT      0x000827 28#define CX18_CS5345_I2C_ADDR		0x4c29#define CX18_Z8F0811_IR_TX_I2C_ADDR	0x7030#define CX18_Z8F0811_IR_RX_I2C_ADDR	0x7131 32/* This array should match the CX18_HW_ defines */33static const u8 hw_addrs[] = {34	0,				/* CX18_HW_TUNER */35	0,				/* CX18_HW_TVEEPROM */36	CX18_CS5345_I2C_ADDR,		/* CX18_HW_CS5345 */37	0,				/* CX18_HW_DVB */38	0,				/* CX18_HW_418_AV */39	0,				/* CX18_HW_GPIO_MUX */40	0,				/* CX18_HW_GPIO_RESET_CTRL */41	CX18_Z8F0811_IR_RX_I2C_ADDR,	/* CX18_HW_Z8F0811_IR_HAUP */42};43 44/* This array should match the CX18_HW_ defines */45/* This might well become a card-specific array */46static const u8 hw_bus[] = {47	1,	/* CX18_HW_TUNER */48	0,	/* CX18_HW_TVEEPROM */49	0,	/* CX18_HW_CS5345 */50	0,	/* CX18_HW_DVB */51	0,	/* CX18_HW_418_AV */52	0,	/* CX18_HW_GPIO_MUX */53	0,	/* CX18_HW_GPIO_RESET_CTRL */54	0,	/* CX18_HW_Z8F0811_IR_HAUP */55};56 57/* This array should match the CX18_HW_ defines */58static const char * const hw_devicenames[] = {59	"tuner",60	"tveeprom",61	"cs5345",62	"cx23418_DTV",63	"cx23418_AV",64	"gpio_mux",65	"gpio_reset_ctrl",66	"ir_z8f0811_haup",67};68 69static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw,70			   const char *type, u8 addr)71{72	struct i2c_board_info info;73	struct IR_i2c_init_data *init_data = &cx->ir_i2c_init_data;74	unsigned short addr_list[2] = { addr, I2C_CLIENT_END };75 76	memset(&info, 0, sizeof(struct i2c_board_info));77	strscpy(info.type, type, I2C_NAME_SIZE);78 79	/* Our default information for ir-kbd-i2c.c to use */80	switch (hw) {81	case CX18_HW_Z8F0811_IR_HAUP:82		init_data->ir_codes = RC_MAP_HAUPPAUGE;83		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;84		init_data->type = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE |85							RC_PROTO_BIT_RC6_6A_32;86		init_data->name = cx->card_name;87		info.platform_data = init_data;88		break;89	}90 91	return IS_ERR(i2c_new_scanned_device(adap, &info, addr_list, NULL)) ?92	       -1 : 0;93}94 95int cx18_i2c_register(struct cx18 *cx, unsigned idx)96{97	struct v4l2_subdev *sd;98	int bus = hw_bus[idx];99	struct i2c_adapter *adap = &cx->i2c_adap[bus];100	const char *type = hw_devicenames[idx];101	u32 hw = 1 << idx;102 103	if (hw == CX18_HW_TUNER) {104		/* special tuner group handling */105		sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,106				adap, type, 0, cx->card_i2c->radio);107		if (sd != NULL)108			sd->grp_id = hw;109		sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,110				adap, type, 0, cx->card_i2c->demod);111		if (sd != NULL)112			sd->grp_id = hw;113		sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,114				adap, type, 0, cx->card_i2c->tv);115		if (sd != NULL)116			sd->grp_id = hw;117		return sd != NULL ? 0 : -1;118	}119 120	if (hw == CX18_HW_Z8F0811_IR_HAUP)121		return cx18_i2c_new_ir(cx, adap, hw, type, hw_addrs[idx]);122 123	/* Is it not an I2C device or one we do not wish to register? */124	if (!hw_addrs[idx])125		return -1;126 127	/* It's an I2C device other than an analog tuner or IR chip */128	sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, type, hw_addrs[idx],129				 NULL);130	if (sd != NULL)131		sd->grp_id = hw;132	return sd != NULL ? 0 : -1;133}134 135/* Find the first member of the subdev group id in hw */136struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw)137{138	struct v4l2_subdev *result = NULL;139	struct v4l2_subdev *sd;140 141	spin_lock(&cx->v4l2_dev.lock);142	v4l2_device_for_each_subdev(sd, &cx->v4l2_dev) {143		if (sd->grp_id == hw) {144			result = sd;145			break;146		}147	}148	spin_unlock(&cx->v4l2_dev.lock);149	return result;150}151 152static void cx18_setscl(void *data, int state)153{154	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;155	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;156	u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;157	u32 r = cx18_read_reg(cx, addr);158 159	if (state)160		cx18_write_reg(cx, r | SETSCL_BIT, addr);161	else162		cx18_write_reg(cx, r & ~SETSCL_BIT, addr);163}164 165static void cx18_setsda(void *data, int state)166{167	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;168	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;169	u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;170	u32 r = cx18_read_reg(cx, addr);171 172	if (state)173		cx18_write_reg(cx, r | SETSDL_BIT, addr);174	else175		cx18_write_reg(cx, r & ~SETSDL_BIT, addr);176}177 178static int cx18_getscl(void *data)179{180	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;181	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;182	u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;183 184	return cx18_read_reg(cx, addr) & GETSCL_BIT;185}186 187static int cx18_getsda(void *data)188{189	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;190	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;191	u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;192 193	return cx18_read_reg(cx, addr) & GETSDL_BIT;194}195 196/* template for i2c-bit-algo */197static const struct i2c_adapter cx18_i2c_adap_template = {198	.name = "cx18 i2c driver",199	.algo = NULL,                   /* set by i2c-algo-bit */200	.algo_data = NULL,              /* filled from template */201	.owner = THIS_MODULE,202};203 204#define CX18_SCL_PERIOD (10) /* usecs. 10 usec is period for a 100 KHz clock */205#define CX18_ALGO_BIT_TIMEOUT (2) /* seconds */206 207static const struct i2c_algo_bit_data cx18_i2c_algo_template = {208	.setsda		= cx18_setsda,209	.setscl		= cx18_setscl,210	.getsda		= cx18_getsda,211	.getscl		= cx18_getscl,212	.udelay		= CX18_SCL_PERIOD/2,       /* 1/2 clock period in usec*/213	.timeout	= CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */214};215 216/* init + register i2c adapter */217int init_cx18_i2c(struct cx18 *cx)218{219	int i, err;220	CX18_DEBUG_I2C("i2c init\n");221 222	for (i = 0; i < 2; i++) {223		/* Setup algorithm for adapter */224		cx->i2c_algo[i] = cx18_i2c_algo_template;225		cx->i2c_algo_cb_data[i].cx = cx;226		cx->i2c_algo_cb_data[i].bus_index = i;227		cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i];228 229		/* Setup adapter */230		cx->i2c_adap[i] = cx18_i2c_adap_template;231		cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];232		sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),233				" #%d-%d", cx->instance, i);234		i2c_set_adapdata(&cx->i2c_adap[i], &cx->v4l2_dev);235		cx->i2c_adap[i].dev.parent = &cx->pci_dev->dev;236	}237 238	if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) {239		/* Reset/Unreset I2C hardware block */240		/* Clock select 220MHz */241		cx18_write_reg_expect(cx, 0x10000000, 0xc71004,242					  0x00000000, 0x10001000);243		/* Clock Enable */244		cx18_write_reg_expect(cx, 0x10001000, 0xc71024,245					  0x00001000, 0x10001000);246	}247	/* courtesy of Steven Toth <stoth@hauppauge.com> */248	cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);249	mdelay(10);250	cx18_write_reg_expect(cx, 0x00c000c0, 0xc7001c, 0x000000c0, 0x00c000c0);251	mdelay(10);252	cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);253	mdelay(10);254 255	/* Set to edge-triggered intrs. */256	cx18_write_reg(cx, 0x00c00000, 0xc730c8);257	/* Clear any stale intrs */258	cx18_write_reg_expect(cx, HW2_I2C1_INT|HW2_I2C2_INT, HW2_INT_CLR_STATUS,259		       ~(HW2_I2C1_INT|HW2_I2C2_INT), HW2_I2C1_INT|HW2_I2C2_INT);260 261	/* Hw I2C1 Clock Freq ~100kHz */262	cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR);263	cx18_setscl(&cx->i2c_algo_cb_data[0], 1);264	cx18_setsda(&cx->i2c_algo_cb_data[0], 1);265 266	/* Hw I2C2 Clock Freq ~100kHz */267	cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR);268	cx18_setscl(&cx->i2c_algo_cb_data[1], 1);269	cx18_setsda(&cx->i2c_algo_cb_data[1], 1);270 271	cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,272		     core, reset, (u32) CX18_GPIO_RESET_I2C);273 274	err = i2c_bit_add_bus(&cx->i2c_adap[0]);275	if (err)276		goto err;277	err = i2c_bit_add_bus(&cx->i2c_adap[1]);278	if (err)279		goto err_del_bus_0;280	return 0;281 282 err_del_bus_0:283	i2c_del_adapter(&cx->i2c_adap[0]);284 err:285	return err;286}287 288void exit_cx18_i2c(struct cx18 *cx)289{290	int i;291	CX18_DEBUG_I2C("i2c exit\n");292	cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4,293							CX18_REG_I2C_1_WR);294	cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4,295							CX18_REG_I2C_2_WR);296 297	for (i = 0; i < 2; i++) {298		i2c_del_adapter(&cx->i2c_adap[i]);299	}300}301 302/*303   Hauppauge HVR1600 should have:304   32 cx24227305   98 unknown306   a0 eeprom307   c2 tuner308   e? zilog ir309   */310