Linux Audio

Check our new training course

Loading...
  1/*
  2
  3    cx88-vp3054-i2c.c  --  support for the secondary I2C bus of the
  4			   DNTV Live! DVB-T Pro (VP-3054), wired as:
  5			   GPIO[0] -> SCL, GPIO[1] -> SDA
  6
  7    (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
  8
  9    This program is free software; you can redistribute it and/or modify
 10    it under the terms of the GNU General Public License as published by
 11    the Free Software Foundation; either version 2 of the License, or
 12    (at your option) any later version.
 13
 14    This program is distributed in the hope that it will be useful,
 15    but WITHOUT ANY WARRANTY; without even the implied warranty of
 16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17    GNU General Public License for more details.
 18
 19    You should have received a copy of the GNU General Public License
 20    along with this program; if not, write to the Free Software
 21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 22
 23*/
 24
 25#include <linux/module.h>
 26#include <linux/slab.h>
 27#include <linux/init.h>
 28
 29#include <asm/io.h>
 30
 31#include "cx88.h"
 32#include "cx88-vp3054-i2c.h"
 33
 34MODULE_DESCRIPTION("driver for cx2388x VP3054 design");
 35MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
 36MODULE_LICENSE("GPL");
 37
 38/* ----------------------------------------------------------------------- */
 39
 40static void vp3054_bit_setscl(void *data, int state)
 41{
 42	struct cx8802_dev *dev = data;
 43	struct cx88_core *core = dev->core;
 44	struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
 45
 46	if (state) {
 47		vp3054_i2c->state |=  0x0001;	/* SCL high */
 48		vp3054_i2c->state &= ~0x0100;	/* external pullup */
 49	} else {
 50		vp3054_i2c->state &= ~0x0001;	/* SCL low */
 51		vp3054_i2c->state |=  0x0100;	/* drive pin */
 52	}
 53	cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state);
 54	cx_read(MO_GP0_IO);
 55}
 56
 57static void vp3054_bit_setsda(void *data, int state)
 58{
 59	struct cx8802_dev *dev = data;
 60	struct cx88_core *core = dev->core;
 61	struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
 62
 63	if (state) {
 64		vp3054_i2c->state |=  0x0002;	/* SDA high */
 65		vp3054_i2c->state &= ~0x0200;	/* tristate pin */
 66	} else {
 67		vp3054_i2c->state &= ~0x0002;	/* SDA low */
 68		vp3054_i2c->state |=  0x0200;	/* drive pin */
 69	}
 70	cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state);
 71	cx_read(MO_GP0_IO);
 72}
 73
 74static int vp3054_bit_getscl(void *data)
 75{
 76	struct cx8802_dev *dev = data;
 77	struct cx88_core *core = dev->core;
 78	u32 state;
 79
 80	state = cx_read(MO_GP0_IO);
 81	return (state & 0x01) ? 1 : 0;
 82}
 83
 84static int vp3054_bit_getsda(void *data)
 85{
 86	struct cx8802_dev *dev = data;
 87	struct cx88_core *core = dev->core;
 88	u32 state;
 89
 90	state = cx_read(MO_GP0_IO);
 91	return (state & 0x02) ? 1 : 0;
 92}
 93
 94/* ----------------------------------------------------------------------- */
 95
 96static const struct i2c_algo_bit_data vp3054_i2c_algo_template = {
 97	.setsda  = vp3054_bit_setsda,
 98	.setscl  = vp3054_bit_setscl,
 99	.getsda  = vp3054_bit_getsda,
100	.getscl  = vp3054_bit_getscl,
101	.udelay  = 16,
102	.timeout = 200,
103};
104
105/* ----------------------------------------------------------------------- */
106
107int vp3054_i2c_probe(struct cx8802_dev *dev)
108{
109	struct cx88_core *core = dev->core;
110	struct vp3054_i2c_state *vp3054_i2c;
111	int rc;
112
113	if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
114		return 0;
115
116	vp3054_i2c = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
117	if (vp3054_i2c == NULL)
118		return -ENOMEM;
119	dev->vp3054 = vp3054_i2c;
120
121	memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
122	       sizeof(vp3054_i2c->algo));
123
124	vp3054_i2c->adap.dev.parent = &dev->pci->dev;
125	strlcpy(vp3054_i2c->adap.name, core->name,
126		sizeof(vp3054_i2c->adap.name));
127	vp3054_i2c->adap.owner = THIS_MODULE;
128	vp3054_i2c->algo.data = dev;
129	i2c_set_adapdata(&vp3054_i2c->adap, dev);
130	vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
131
132	vp3054_bit_setscl(dev,1);
133	vp3054_bit_setsda(dev,1);
134
135	rc = i2c_bit_add_bus(&vp3054_i2c->adap);
136	if (0 != rc) {
137		printk("%s: vp3054_i2c register FAILED\n", core->name);
138
139		kfree(dev->vp3054);
140		dev->vp3054 = NULL;
141	}
142
143	return rc;
144}
145
146void vp3054_i2c_remove(struct cx8802_dev *dev)
147{
148	struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
149
150	if (vp3054_i2c == NULL ||
151	    dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
152		return;
153
154	i2c_del_adapter(&vp3054_i2c->adap);
155	kfree(vp3054_i2c);
156}
157
158EXPORT_SYMBOL(vp3054_i2c_probe);
159EXPORT_SYMBOL(vp3054_i2c_remove);