Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/cx88/cx88-vp3054-i2c.c
17956 views
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 <[email protected]>
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
34
MODULE_DESCRIPTION("driver for cx2388x VP3054 design");
35
MODULE_AUTHOR("Chris Pascoe <[email protected]>");
36
MODULE_LICENSE("GPL");
37
38
/* ----------------------------------------------------------------------- */
39
40
static 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
57
static 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
74
static 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
84
static 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
96
static 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
107
int 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
146
void 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
158
EXPORT_SYMBOL(vp3054_i2c_probe);
159
EXPORT_SYMBOL(vp3054_i2c_remove);
160
161