V4L/DVB (4763): Pvrusb2: Implement IR reception for 24xxx devices

Unlike 29xxx devices, the 24xxx model series does not have a dedicated
I2C device for reception of IR codes.  Instead IR is handled directly
by the FX2 microcontroller and the results are communicated via
commands to the FX2.  Rather than implement a whole new IR reception
pathway for 24xxx devices, this changeset instead emulates the
presence of the 29xxx device's I2C based IR receiver by intercepting
commands to that chip and issuing appropriate FX2 commands to do the
needed action.  This has the result of allowing all the usual IR
frameworks (ir-kbd-i2c or lirc) to continue working unmodified for
24xxx devices.

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Mike Isely 2006-10-15 21:35:14 -03:00 committed by Mauro Carvalho Chehab
parent c85f49d49f
commit cc75aede1b
1 changed files with 77 additions and 4 deletions

View File

@ -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.