| From ed87d33ddbcd9a1c3b5ae87995da34e6f51a862c Mon Sep 17 00:00:00 2001 |
| From: Ian Abbott <abbotti@mev.co.uk> |
| Date: Mon, 6 Apr 2020 15:20:15 +0100 |
| Subject: staging: comedi: dt2815: fix writing hi byte of analog output |
| |
| From: Ian Abbott <abbotti@mev.co.uk> |
| |
| commit ed87d33ddbcd9a1c3b5ae87995da34e6f51a862c upstream. |
| |
| The DT2815 analog output command is 16 bits wide, consisting of the |
| 12-bit sample value in bits 15 to 4, the channel number in bits 3 to 1, |
| and a voltage or current selector in bit 0. Both bytes of the 16-bit |
| command need to be written in turn to a single 8-bit data register. |
| However, the driver currently only writes the low 8-bits. It is broken |
| and appears to have always been broken. |
| |
| Electronic copies of the DT2815 User's Manual seem impossible to find |
| online, but looking at the source code, a best guess for the sequence |
| the driver intended to use to write the analog output command is as |
| follows: |
| |
| 1. Wait for the status register to read 0x00. |
| 2. Write the low byte of the command to the data register. |
| 3. Wait for the status register to read 0x80. |
| 4. Write the high byte of the command to the data register. |
| |
| Step 4 is missing from the driver. Add step 4 to (hopefully) fix the |
| driver. |
| |
| Also add a "FIXME" comment about setting bit 0 of the low byte of the |
| command. Supposedly, it is used to choose between voltage output and |
| current output, but the current driver always sets it to 1. |
| |
| Signed-off-by: Ian Abbott <abbotti@mev.co.uk> |
| Cc: stable <stable@vger.kernel.org> |
| Link: https://lore.kernel.org/r/20200406142015.126982-1-abbotti@mev.co.uk |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/staging/comedi/drivers/dt2815.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| --- a/drivers/staging/comedi/drivers/dt2815.c |
| +++ b/drivers/staging/comedi/drivers/dt2815.c |
| @@ -92,6 +92,7 @@ static int dt2815_ao_insn(struct comedi_ |
| int ret; |
| |
| for (i = 0; i < insn->n; i++) { |
| + /* FIXME: lo bit 0 chooses voltage output or current output */ |
| lo = ((data[i] & 0x0f) << 4) | (chan << 1) | 0x01; |
| hi = (data[i] & 0xff0) >> 4; |
| |
| @@ -105,6 +106,8 @@ static int dt2815_ao_insn(struct comedi_ |
| if (ret) |
| return ret; |
| |
| + outb(hi, dev->iobase + DT2815_DATA); |
| + |
| devpriv->ao_readback[chan] = data[i]; |
| } |
| return i; |