ALSA: oxygen: Xonar DG(X): add new CS4245 SPI functions
authorRoman Volkov <v1ron@mail.ru>
Fri, 24 Jan 2014 12:18:08 +0000 (16:18 +0400)
committerClemens Ladisch <clemens@ladisch.de>
Wed, 29 Jan 2014 19:45:46 +0000 (20:45 +0100)
Add the new SPI write and read functions. The SPI read function
is used for creating initial registers dump and may be used for
debugging purposes. SPI operations are cached, so there is a new
function to manage the cache (shadow). I have to remove
the shift from the CS4245_SPI_* constants, since when
we are performing the reading, we need to shift by 8 instead
of 16.

Signed-off-by: Roman Volkov <v1ron@mail.ru>
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
sound/pci/oxygen/cs4245.h
sound/pci/oxygen/xonar_dg.c
sound/pci/oxygen/xonar_dg.h

index 5e0197e07dd1e50eb5ea4cea8e18fae458d37d3c..99098657695a4f4748bfb8cdac7a8984cc39ce98 100644 (file)
 #define CS4245_ADC_OVFL                0x02
 #define CS4245_ADC_UNDRFL      0x01
 
+#define CS4245_SPI_ADDRESS_S   (0x9e << 16)
+#define CS4245_SPI_WRITE_S     (0 << 16)
 
-#define CS4245_SPI_ADDRESS     (0x9e << 16)
-#define CS4245_SPI_WRITE       (0 << 16)
+#define CS4245_SPI_ADDRESS     0x9e
+#define CS4245_SPI_WRITE       0
+#define CS4245_SPI_READ                1
index c175720f1c7a71775b0d58cb3c5753351902b0d9..2518c611d5c5988a30b3dd9a7d20954742fd7318 100644 (file)
 #include "xonar_dg.h"
 #include "cs4245.h"
 
+int cs4245_write_spi(struct oxygen *chip, u8 reg)
+{
+       struct dg *data = chip->model_data;
+       unsigned int packet;
+
+       packet = reg << 8;
+       packet |= (CS4245_SPI_ADDRESS | CS4245_SPI_WRITE) << 16;
+       packet |= data->cs4245_shadow[reg];
+
+       return oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
+                               OXYGEN_SPI_DATA_LENGTH_3 |
+                               OXYGEN_SPI_CLOCK_1280 |
+                               (0 << OXYGEN_SPI_CODEC_SHIFT) |
+                               OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
+                               packet);
+}
+
+int cs4245_read_spi(struct oxygen *chip, u8 addr)
+{
+       struct dg *data = chip->model_data;
+       int ret;
+
+       ret = oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
+               OXYGEN_SPI_DATA_LENGTH_2 |
+               OXYGEN_SPI_CEN_LATCH_CLOCK_HI |
+               OXYGEN_SPI_CLOCK_1280 | (0 << OXYGEN_SPI_CODEC_SHIFT),
+               ((CS4245_SPI_ADDRESS | CS4245_SPI_WRITE) << 8) | addr);
+       if (ret < 0)
+               return ret;
+
+       ret = oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
+               OXYGEN_SPI_DATA_LENGTH_2 |
+               OXYGEN_SPI_CEN_LATCH_CLOCK_HI |
+               OXYGEN_SPI_CLOCK_1280 | (0 << OXYGEN_SPI_CODEC_SHIFT),
+               (CS4245_SPI_ADDRESS | CS4245_SPI_READ) << 8);
+       if (ret < 0)
+               return ret;
+
+       data->cs4245_shadow[addr] = oxygen_read8(chip, OXYGEN_SPI_DATA1);
+
+       return 0;
+}
+
+int cs4245_shadow_control(struct oxygen *chip, enum cs4245_shadow_operation op)
+{
+       struct dg *data = chip->model_data;
+       unsigned char addr;
+       int ret;
+
+       for (addr = 1; addr < ARRAY_SIZE(data->cs4245_shadow); addr++) {
+               ret = (op == CS4245_SAVE_TO_SHADOW ?
+                       cs4245_read_spi(chip, addr) :
+                       cs4245_write_spi(chip, addr));
+               if (ret < 0)
+                       return ret;
+       }
+       return 0;
+}
+
 static void cs4245_write(struct oxygen *chip, unsigned int reg, u8 value)
 {
        struct dg *data = chip->model_data;
@@ -73,8 +132,8 @@ static void cs4245_write(struct oxygen *chip, unsigned int reg, u8 value)
                         OXYGEN_SPI_CLOCK_1280 |
                         (0 << OXYGEN_SPI_CODEC_SHIFT) |
                         OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
-                        CS4245_SPI_ADDRESS |
-                        CS4245_SPI_WRITE |
+                        CS4245_SPI_ADDRESS_S |
+                        CS4245_SPI_WRITE_S |
                         (reg << 8) | value);
        data->cs4245_regs[reg] = value;
 }
index 0812692248509df6d8e39a31f2370ac20c8d7222..f2fa846d724664487e8efd9088528af29467d2ea 100644 (file)
 #define PLAYBACK_DST_HP_FP     1
 #define PLAYBACK_DST_MULTICH   2
 
+enum cs4245_shadow_operation {
+       CS4245_SAVE_TO_SHADOW,
+       CS4245_LOAD_FROM_SHADOW
+};
+
 struct dg {
+       /* shadow copy of the CS4245 register space */
+       unsigned char cs4245_shadow[17];
        unsigned int output_sel;
        s8 input_vol[4][2];
        unsigned int input_sel;