|
@@ -185,6 +185,79 @@ static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+/* This is a special entry point for cases of I2C transaction attempts to
|
|
|
+ the IR receiver. The implementation here simulates the IR receiver by
|
|
|
+ issuing a command to the FX2 firmware and using that response to return
|
|
|
+ what the real I2C receiver would have returned. We use this for 24xxx
|
|
|
+ devices, where the IR receiver chip has been removed and replaced with
|
|
|
+ FX2 related logic. */
|
|
|
+static int i2c_24xxx_ir(struct pvr2_hdw *hdw,
|
|
|
+ u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
|
|
|
+{
|
|
|
+ u8 dat[4];
|
|
|
+ unsigned int stat;
|
|
|
+
|
|
|
+ if (!(rlen || wlen)) {
|
|
|
+ /* This is a probe attempt. Just let it succeed. */
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* We don't understand this kind of transaction */
|
|
|
+ if ((wlen != 0) || (rlen == 0)) return -EIO;
|
|
|
+
|
|
|
+ if (rlen < 3) {
|
|
|
+ /* Mike Isely <isely@pobox.com> Appears to be a probe
|
|
|
+ attempt from lirc. Just fill in zeroes and return. If
|
|
|
+ we try instead to do the full transaction here, then bad
|
|
|
+ things seem to happen within the lirc driver module
|
|
|
+ (version 0.8.0-7 sources from Debian, when run under
|
|
|
+ vanilla 2.6.17.6 kernel) - and I don't have the patience
|
|
|
+ to chase it down. */
|
|
|
+ if (rlen > 0) rdata[0] = 0;
|
|
|
+ if (rlen > 1) rdata[1] = 0;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Issue a command to the FX2 to read the IR receiver. */
|
|
|
+ LOCK_TAKE(hdw->ctl_lock); do {
|
|
|
+ hdw->cmd_buffer[0] = 0xec;
|
|
|
+ stat = pvr2_send_request(hdw,
|
|
|
+ hdw->cmd_buffer,1,
|
|
|
+ hdw->cmd_buffer,4);
|
|
|
+ dat[0] = hdw->cmd_buffer[0];
|
|
|
+ dat[1] = hdw->cmd_buffer[1];
|
|
|
+ dat[2] = hdw->cmd_buffer[2];
|
|
|
+ dat[3] = hdw->cmd_buffer[3];
|
|
|
+ } while (0); LOCK_GIVE(hdw->ctl_lock);
|
|
|
+
|
|
|
+ /* Give up if that operation failed. */
|
|
|
+ if (stat != 0) return stat;
|
|
|
+
|
|
|
+ /* Mangle the results into something that looks like the real IR
|
|
|
+ receiver. */
|
|
|
+ rdata[2] = 0xc1;
|
|
|
+ if (dat[0] != 1) {
|
|
|
+ /* No code received. */
|
|
|
+ rdata[0] = 0;
|
|
|
+ rdata[1] = 0;
|
|
|
+ } else {
|
|
|
+ u16 val;
|
|
|
+ /* Mash the FX2 firmware-provided IR code into something
|
|
|
+ that the normal i2c chip-level driver expects. */
|
|
|
+ val = dat[1];
|
|
|
+ val <<= 8;
|
|
|
+ val |= dat[2];
|
|
|
+ val >>= 1;
|
|
|
+ val &= ~0x0003;
|
|
|
+ val |= 0x8000;
|
|
|
+ rdata[0] = (val >> 8) & 0xffu;
|
|
|
+ rdata[1] = val & 0xffu;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/* This is a special entry point that is entered if an I2C operation is
|
|
|
attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this
|
|
|
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)
|
|
|
{
|
|
|
unsigned int idx;
|
|
|
|
|
|
- // The default action for all possible I2C addresses is just to do
|
|
|
- // the transfer normally.
|
|
|
+ /* The default action for all possible I2C addresses is just to do
|
|
|
+ the transfer normally. */
|
|
|
for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
|
|
|
hdw->i2c_func[idx] = pvr2_i2c_basic_op;
|
|
|
}
|
|
|
|
|
|
- // If however we're dealing with new hardware, insert some hacks in
|
|
|
- // the I2C transfer stack to let things work better.
|
|
|
+ /* However, deal with various special cases for 24xxx hardware. */
|
|
|
if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
|
|
|
hdw->i2c_func[0x1b] = i2c_hack_wm8775;
|
|
|
hdw->i2c_func[0x44] = i2c_hack_cx25840;
|
|
|
+ hdw->i2c_func[0x18] = i2c_24xxx_ir;
|
|
|
}
|
|
|
|
|
|
// Configure the adapter and set up everything else related to it.
|