ALSA: oxygen: Xonar DG(X): add new CS4245 SPI functions

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>

authored by Roman Volkov and committed by Clemens Ladisch bed61935 ddd624c3

+73 -4
+5 -2
sound/pci/oxygen/cs4245.h
··· 102 102 #define CS4245_ADC_OVFL 0x02 103 103 #define CS4245_ADC_UNDRFL 0x01 104 104 105 + #define CS4245_SPI_ADDRESS_S (0x9e << 16) 106 + #define CS4245_SPI_WRITE_S (0 << 16) 105 107 106 - #define CS4245_SPI_ADDRESS (0x9e << 16) 107 - #define CS4245_SPI_WRITE (0 << 16) 108 + #define CS4245_SPI_ADDRESS 0x9e 109 + #define CS4245_SPI_WRITE 0 110 + #define CS4245_SPI_READ 1
+61 -2
sound/pci/oxygen/xonar_dg.c
··· 64 64 #include "xonar_dg.h" 65 65 #include "cs4245.h" 66 66 67 + int cs4245_write_spi(struct oxygen *chip, u8 reg) 68 + { 69 + struct dg *data = chip->model_data; 70 + unsigned int packet; 71 + 72 + packet = reg << 8; 73 + packet |= (CS4245_SPI_ADDRESS | CS4245_SPI_WRITE) << 16; 74 + packet |= data->cs4245_shadow[reg]; 75 + 76 + return oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | 77 + OXYGEN_SPI_DATA_LENGTH_3 | 78 + OXYGEN_SPI_CLOCK_1280 | 79 + (0 << OXYGEN_SPI_CODEC_SHIFT) | 80 + OXYGEN_SPI_CEN_LATCH_CLOCK_HI, 81 + packet); 82 + } 83 + 84 + int cs4245_read_spi(struct oxygen *chip, u8 addr) 85 + { 86 + struct dg *data = chip->model_data; 87 + int ret; 88 + 89 + ret = oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | 90 + OXYGEN_SPI_DATA_LENGTH_2 | 91 + OXYGEN_SPI_CEN_LATCH_CLOCK_HI | 92 + OXYGEN_SPI_CLOCK_1280 | (0 << OXYGEN_SPI_CODEC_SHIFT), 93 + ((CS4245_SPI_ADDRESS | CS4245_SPI_WRITE) << 8) | addr); 94 + if (ret < 0) 95 + return ret; 96 + 97 + ret = oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | 98 + OXYGEN_SPI_DATA_LENGTH_2 | 99 + OXYGEN_SPI_CEN_LATCH_CLOCK_HI | 100 + OXYGEN_SPI_CLOCK_1280 | (0 << OXYGEN_SPI_CODEC_SHIFT), 101 + (CS4245_SPI_ADDRESS | CS4245_SPI_READ) << 8); 102 + if (ret < 0) 103 + return ret; 104 + 105 + data->cs4245_shadow[addr] = oxygen_read8(chip, OXYGEN_SPI_DATA1); 106 + 107 + return 0; 108 + } 109 + 110 + int cs4245_shadow_control(struct oxygen *chip, enum cs4245_shadow_operation op) 111 + { 112 + struct dg *data = chip->model_data; 113 + unsigned char addr; 114 + int ret; 115 + 116 + for (addr = 1; addr < ARRAY_SIZE(data->cs4245_shadow); addr++) { 117 + ret = (op == CS4245_SAVE_TO_SHADOW ? 118 + cs4245_read_spi(chip, addr) : 119 + cs4245_write_spi(chip, addr)); 120 + if (ret < 0) 121 + return ret; 122 + } 123 + return 0; 124 + } 125 + 67 126 static void cs4245_write(struct oxygen *chip, unsigned int reg, u8 value) 68 127 { 69 128 struct dg *data = chip->model_data; ··· 132 73 OXYGEN_SPI_CLOCK_1280 | 133 74 (0 << OXYGEN_SPI_CODEC_SHIFT) | 134 75 OXYGEN_SPI_CEN_LATCH_CLOCK_HI, 135 - CS4245_SPI_ADDRESS | 136 - CS4245_SPI_WRITE | 76 + CS4245_SPI_ADDRESS_S | 77 + CS4245_SPI_WRITE_S | 137 78 (reg << 8) | value); 138 79 data->cs4245_regs[reg] = value; 139 80 }
+7
sound/pci/oxygen/xonar_dg.h
··· 18 18 #define PLAYBACK_DST_HP_FP 1 19 19 #define PLAYBACK_DST_MULTICH 2 20 20 21 + enum cs4245_shadow_operation { 22 + CS4245_SAVE_TO_SHADOW, 23 + CS4245_LOAD_FROM_SHADOW 24 + }; 25 + 21 26 struct dg { 27 + /* shadow copy of the CS4245 register space */ 28 + unsigned char cs4245_shadow[17]; 22 29 unsigned int output_sel; 23 30 s8 input_vol[4][2]; 24 31 unsigned int input_sel;