diff options
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-i2c-core.c')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 3b9012f8e380..f9bb41d8f4f3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -185,6 +185,79 @@ static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw, | |||
185 | } | 185 | } |
186 | } | 186 | } |
187 | 187 | ||
188 | |||
189 | /* This is a special entry point for cases of I2C transaction attempts to | ||
190 | the IR receiver. The implementation here simulates the IR receiver by | ||
191 | issuing a command to the FX2 firmware and using that response to return | ||
192 | what the real I2C receiver would have returned. We use this for 24xxx | ||
193 | devices, where the IR receiver chip has been removed and replaced with | ||
194 | FX2 related logic. */ | ||
195 | static int i2c_24xxx_ir(struct pvr2_hdw *hdw, | ||
196 | u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) | ||
197 | { | ||
198 | u8 dat[4]; | ||
199 | unsigned int stat; | ||
200 | |||
201 | if (!(rlen || wlen)) { | ||
202 | /* This is a probe attempt. Just let it succeed. */ | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /* We don't understand this kind of transaction */ | ||
207 | if ((wlen != 0) || (rlen == 0)) return -EIO; | ||
208 | |||
209 | if (rlen < 3) { | ||
210 | /* Mike Isely <isely@pobox.com> Appears to be a probe | ||
211 | attempt from lirc. Just fill in zeroes and return. If | ||
212 | we try instead to do the full transaction here, then bad | ||
213 | things seem to happen within the lirc driver module | ||
214 | (version 0.8.0-7 sources from Debian, when run under | ||
215 | vanilla 2.6.17.6 kernel) - and I don't have the patience | ||
216 | to chase it down. */ | ||
217 | if (rlen > 0) rdata[0] = 0; | ||
218 | if (rlen > 1) rdata[1] = 0; | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | /* Issue a command to the FX2 to read the IR receiver. */ | ||
223 | LOCK_TAKE(hdw->ctl_lock); do { | ||
224 | hdw->cmd_buffer[0] = 0xec; | ||
225 | stat = pvr2_send_request(hdw, | ||
226 | hdw->cmd_buffer,1, | ||
227 | hdw->cmd_buffer,4); | ||
228 | dat[0] = hdw->cmd_buffer[0]; | ||
229 | dat[1] = hdw->cmd_buffer[1]; | ||
230 | dat[2] = hdw->cmd_buffer[2]; | ||
231 | dat[3] = hdw->cmd_buffer[3]; | ||
232 | } while (0); LOCK_GIVE(hdw->ctl_lock); | ||
233 | |||
234 | /* Give up if that operation failed. */ | ||
235 | if (stat != 0) return stat; | ||
236 | |||
237 | /* Mangle the results into something that looks like the real IR | ||
238 | receiver. */ | ||
239 | rdata[2] = 0xc1; | ||
240 | if (dat[0] != 1) { | ||
241 | /* No code received. */ | ||
242 | rdata[0] = 0; | ||
243 | rdata[1] = 0; | ||
244 | } else { | ||
245 | u16 val; | ||
246 | /* Mash the FX2 firmware-provided IR code into something | ||
247 | that the normal i2c chip-level driver expects. */ | ||
248 | val = dat[1]; | ||
249 | val <<= 8; | ||
250 | val |= dat[2]; | ||
251 | val >>= 1; | ||
252 | val &= ~0x0003; | ||
253 | val |= 0x8000; | ||
254 | rdata[0] = (val >> 8) & 0xffu; | ||
255 | rdata[1] = val & 0xffu; | ||
256 | } | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
188 | /* This is a special entry point that is entered if an I2C operation is | 261 | /* This is a special entry point that is entered if an I2C operation is |
189 | attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this | 262 | attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this |
190 | part doesn't work, but we know it is really there. So let's look for | 263 | part doesn't work, but we know it is really there. So let's look for |
@@ -887,17 +960,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | |||
887 | { | 960 | { |
888 | unsigned int idx; | 961 | unsigned int idx; |
889 | 962 | ||
890 | // The default action for all possible I2C addresses is just to do | 963 | /* The default action for all possible I2C addresses is just to do |
891 | // the transfer normally. | 964 | the transfer normally. */ |
892 | for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) { | 965 | for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) { |
893 | hdw->i2c_func[idx] = pvr2_i2c_basic_op; | 966 | hdw->i2c_func[idx] = pvr2_i2c_basic_op; |
894 | } | 967 | } |
895 | 968 | ||
896 | // If however we're dealing with new hardware, insert some hacks in | 969 | /* However, deal with various special cases for 24xxx hardware. */ |
897 | // the I2C transfer stack to let things work better. | ||
898 | if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { | 970 | if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { |
899 | hdw->i2c_func[0x1b] = i2c_hack_wm8775; | 971 | hdw->i2c_func[0x1b] = i2c_hack_wm8775; |
900 | hdw->i2c_func[0x44] = i2c_hack_cx25840; | 972 | hdw->i2c_func[0x44] = i2c_hack_cx25840; |
973 | hdw->i2c_func[0x18] = i2c_24xxx_ir; | ||
901 | } | 974 | } |
902 | 975 | ||
903 | // Configure the adapter and set up everything else related to it. | 976 | // Configure the adapter and set up everything else related to it. |