diff options
author | Johannes Stezenbach <js@linuxtv.org> | 2005-05-17 00:54:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-05-17 10:59:26 -0400 |
commit | bdc7800122da0b6b008aa9bdafc01e32b6a4576a (patch) | |
tree | ad6496d10897e3595b8f340497c2091015354bc8 | |
parent | c6ee197ccf4af454638c044706f0ba7ef6c1bb76 (diff) |
[PATCH] dvb: flexcop: i2c read fixes
rewrote the i2c-reading-part (no more ack-error ignoring, which was inherited
from the skystar2-driver)
Signed-off-by: Patrick Boettcher <pb@linuxtv.org>
Signed-off-by: Johannes Stezenbach <js@linuxtv.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/media/dvb/b2c2/flexcop-i2c.c | 116 | ||||
-rw-r--r-- | drivers/media/dvb/b2c2/flexcop-reg.h | 3 | ||||
-rw-r--r-- | drivers/media/dvb/b2c2/flexcop.c | 4 |
3 files changed, 63 insertions, 60 deletions
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c index 736251f393c2..be4266d4ae91 100644 --- a/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/drivers/media/dvb/b2c2/flexcop-i2c.c | |||
@@ -9,9 +9,9 @@ | |||
9 | 9 | ||
10 | #define FC_MAX_I2C_RETRIES 100000 | 10 | #define FC_MAX_I2C_RETRIES 100000 |
11 | 11 | ||
12 | static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100, int max_ack_errors) | 12 | static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100) |
13 | { | 13 | { |
14 | int i,ack_errors = 0; | 14 | int i; |
15 | flexcop_ibi_value r; | 15 | flexcop_ibi_value r; |
16 | 16 | ||
17 | r100->tw_sm_c_100.working_start = 1; | 17 | r100->tw_sm_c_100.working_start = 1; |
@@ -31,11 +31,7 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r | |||
31 | } | 31 | } |
32 | } else { | 32 | } else { |
33 | deb_i2c("suffering from an i2c ack_error\n"); | 33 | deb_i2c("suffering from an i2c ack_error\n"); |
34 | if (++ack_errors >= max_ack_errors) | 34 | return -EREMOTEIO; |
35 | break; | ||
36 | |||
37 | fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero); | ||
38 | fc->write_ibi_reg(fc, tw_sm_c_100, *r100); | ||
39 | } | 35 | } |
40 | } | 36 | } |
41 | deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",i); | 37 | deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",i); |
@@ -48,19 +44,30 @@ static int flexcop_i2c_read4(struct flexcop_device *fc, flexcop_ibi_value r100, | |||
48 | int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */ | 44 | int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */ |
49 | ret; | 45 | ret; |
50 | 46 | ||
51 | if ((ret = flexcop_i2c_operation(fc,&r100,30)) != 0) | 47 | if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) { |
52 | return ret; | 48 | /* The Cablestar needs a different kind of i2c-transfer (does not |
53 | 49 | * support "Repeat Start"): | |
54 | r104 = fc->read_ibi_reg(fc,tw_sm_c_104); | 50 | * wait for the ACK failure, |
55 | 51 | * and do a subsequent read with the Bit 30 enabled | |
56 | deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw); | 52 | */ |
53 | r100.tw_sm_c_100.no_base_addr_ack_error = 1; | ||
54 | if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) { | ||
55 | deb_i2c("no_base_addr read failed. %d\n",ret); | ||
56 | return ret; | ||
57 | } | ||
58 | } | ||
57 | 59 | ||
58 | /* there is at least one byte, otherwise we wouldn't be here */ | ||
59 | buf[0] = r100.tw_sm_c_100.data1_reg; | 60 | buf[0] = r100.tw_sm_c_100.data1_reg; |
60 | 61 | ||
61 | if (len > 0) buf[1] = r104.tw_sm_c_104.data2_reg; | 62 | if (len > 0) { |
62 | if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg; | 63 | r104 = fc->read_ibi_reg(fc,tw_sm_c_104); |
63 | if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg; | 64 | deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw); |
65 | |||
66 | /* there is at least one more byte, otherwise we wouldn't be here */ | ||
67 | buf[1] = r104.tw_sm_c_104.data2_reg; | ||
68 | if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg; | ||
69 | if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg; | ||
70 | } | ||
64 | 71 | ||
65 | return 0; | 72 | return 0; |
66 | } | 73 | } |
@@ -82,9 +89,45 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100, | |||
82 | 89 | ||
83 | /* write the additional i2c data before doing the actual i2c operation */ | 90 | /* write the additional i2c data before doing the actual i2c operation */ |
84 | fc->write_ibi_reg(fc,tw_sm_c_104,r104); | 91 | fc->write_ibi_reg(fc,tw_sm_c_104,r104); |
92 | return flexcop_i2c_operation(fc,&r100); | ||
93 | } | ||
94 | |||
95 | int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op, | ||
96 | flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len) | ||
97 | { | ||
98 | int ret; | ||
99 | u16 bytes_to_transfer; | ||
100 | flexcop_ibi_value r100; | ||
101 | |||
102 | deb_i2c("op = %d\n",op); | ||
103 | r100.raw = 0; | ||
104 | r100.tw_sm_c_100.chipaddr = chipaddr; | ||
105 | r100.tw_sm_c_100.twoWS_rw = op; | ||
106 | r100.tw_sm_c_100.twoWS_port_reg = port; | ||
107 | |||
108 | while (len != 0) { | ||
109 | bytes_to_transfer = len > 4 ? 4 : len; | ||
85 | 110 | ||
86 | return flexcop_i2c_operation(fc,&r100,30); | 111 | r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1; |
112 | r100.tw_sm_c_100.baseaddr = addr; | ||
113 | |||
114 | if (op == FC_READ) | ||
115 | ret = flexcop_i2c_read4(fc, r100, buf); | ||
116 | else | ||
117 | ret = flexcop_i2c_write4(fc,r100, buf); | ||
118 | |||
119 | if (ret < 0) | ||
120 | return ret; | ||
121 | |||
122 | buf += bytes_to_transfer; | ||
123 | addr += bytes_to_transfer; | ||
124 | len -= bytes_to_transfer; | ||
125 | }; | ||
126 | |||
127 | return 0; | ||
87 | } | 128 | } |
129 | /* exported for PCI i2c */ | ||
130 | EXPORT_SYMBOL(flexcop_i2c_request); | ||
88 | 131 | ||
89 | /* master xfer callback for demodulator */ | 132 | /* master xfer callback for demodulator */ |
90 | static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) | 133 | static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) |
@@ -123,43 +166,6 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs | |||
123 | return ret; | 166 | return ret; |
124 | } | 167 | } |
125 | 168 | ||
126 | int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op, | ||
127 | flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len) | ||
128 | { | ||
129 | int ret; | ||
130 | u16 bytes_to_transfer; | ||
131 | flexcop_ibi_value r100; | ||
132 | |||
133 | deb_i2c("op = %d\n",op); | ||
134 | r100.raw = 0; | ||
135 | r100.tw_sm_c_100.chipaddr = chipaddr; | ||
136 | r100.tw_sm_c_100.twoWS_rw = op; | ||
137 | r100.tw_sm_c_100.twoWS_port_reg = port; | ||
138 | |||
139 | while (len != 0) { | ||
140 | bytes_to_transfer = len > 4 ? 4 : len; | ||
141 | |||
142 | r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1; | ||
143 | r100.tw_sm_c_100.baseaddr = addr; | ||
144 | |||
145 | if (op == FC_READ) | ||
146 | ret = flexcop_i2c_read4(fc, r100, buf); | ||
147 | else | ||
148 | ret = flexcop_i2c_write4(fc,r100, buf); | ||
149 | |||
150 | if (ret < 0) | ||
151 | return ret; | ||
152 | |||
153 | buf += bytes_to_transfer; | ||
154 | addr += bytes_to_transfer; | ||
155 | len -= bytes_to_transfer; | ||
156 | }; | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | /* exported for PCI i2c */ | ||
161 | EXPORT_SYMBOL(flexcop_i2c_request); | ||
162 | |||
163 | static u32 flexcop_i2c_func(struct i2c_adapter *adapter) | 169 | static u32 flexcop_i2c_func(struct i2c_adapter *adapter) |
164 | { | 170 | { |
165 | return I2C_FUNC_I2C; | 171 | return I2C_FUNC_I2C; |
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h index 41835c5280ae..5e131be55cb3 100644 --- a/drivers/media/dvb/b2c2/flexcop-reg.h +++ b/drivers/media/dvb/b2c2/flexcop-reg.h | |||
@@ -692,9 +692,10 @@ typedef enum { | |||
692 | wan_ctrl_reg_71c = 0x71c, | 692 | wan_ctrl_reg_71c = 0x71c, |
693 | } flexcop_ibi_register; | 693 | } flexcop_ibi_register; |
694 | 694 | ||
695 | #define flexcop_set_ibi_value(reg,attr,val) \ | 695 | #define flexcop_set_ibi_value(reg,attr,val) { \ |
696 | flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \ | 696 | flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \ |
697 | v.reg.attr = val; \ | 697 | v.reg.attr = val; \ |
698 | fc->write_ibi_reg(fc,reg,v); \ | 698 | fc->write_ibi_reg(fc,reg,v); \ |
699 | } | ||
699 | 700 | ||
700 | #endif | 701 | #endif |
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c index df55e4c8ecd8..8b5d14dd36e3 100644 --- a/drivers/media/dvb/b2c2/flexcop.c +++ b/drivers/media/dvb/b2c2/flexcop.c | |||
@@ -184,10 +184,6 @@ static void flexcop_reset(struct flexcop_device *fc) | |||
184 | fc->write_ibi_reg(fc,misc_204,v204); | 184 | fc->write_ibi_reg(fc,misc_204,v204); |
185 | v204.misc_204.Per_reset_sig = 1; | 185 | v204.misc_204.Per_reset_sig = 1; |
186 | fc->write_ibi_reg(fc,misc_204,v204); | 186 | fc->write_ibi_reg(fc,misc_204,v204); |
187 | |||
188 | /* v208.raw = 0; | ||
189 | v208.ctrl_208.Null_filter_sig = 1; | ||
190 | fc->write_ibi_reg(fc,ctrl_208,v208);*/ | ||
191 | } | 187 | } |
192 | 188 | ||
193 | struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len) | 189 | struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len) |