aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/oxygen/xonar_cs43xx.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-09-28 05:18:45 -0400
committerTakashi Iwai <tiwai@suse.de>2009-09-28 05:54:29 -0400
commit6f0de3ce068e48b033b5e4d0822b47218e9d206c (patch)
tree6e4e9c054a867e5deee94df181701dedc99e4275 /sound/pci/oxygen/xonar_cs43xx.c
parentdc0adf48daa81b05765d3c5ebab76321f77e9d21 (diff)
sound: oxygen: cache codec registers
Keep a cache of codec registers to avoid unnecessary writes. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/oxygen/xonar_cs43xx.c')
-rw-r--r--sound/pci/oxygen/xonar_cs43xx.c140
1 files changed, 87 insertions, 53 deletions
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c
index a8ec4e8271a4..330c5e755917 100644
--- a/sound/pci/oxygen/xonar_cs43xx.c
+++ b/sound/pci/oxygen/xonar_cs43xx.c
@@ -69,62 +69,58 @@
69 69
70struct xonar_cs43xx { 70struct xonar_cs43xx {
71 struct xonar_generic generic; 71 struct xonar_generic generic;
72 u8 cs4398_fm; 72 u8 cs4398_regs[7];
73 u8 cs4362a_fm; 73 u8 cs4362a_regs[15];
74 u8 cs4362a_fm_c;
75}; 74};
76 75
77static void cs4398_write(struct oxygen *chip, u8 reg, u8 value) 76static void cs4398_write(struct oxygen *chip, u8 reg, u8 value)
78{ 77{
79 oxygen_write_i2c(chip, I2C_DEVICE_CS4398, reg, value); 78 struct xonar_cs43xx *data = chip->model_data;
80}
81 79
82static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value) 80 oxygen_write_i2c(chip, I2C_DEVICE_CS4398, reg, value);
83{ 81 if (reg < ARRAY_SIZE(data->cs4398_regs))
84 oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value); 82 data->cs4398_regs[reg] = value;
85} 83}
86 84
87static void update_cs4362a_volumes(struct oxygen *chip) 85static void cs4398_write_cached(struct oxygen *chip, u8 reg, u8 value)
88{ 86{
89 u8 mute; 87 struct xonar_cs43xx *data = chip->model_data;
90 88
91 mute = chip->dac_mute ? CS4362A_MUTE : 0; 89 if (value != data->cs4398_regs[reg])
92 cs4362a_write(chip, 7, (127 - chip->dac_volume[2]) | mute); 90 cs4398_write(chip, reg, value);
93 cs4362a_write(chip, 8, (127 - chip->dac_volume[3]) | mute);
94 cs4362a_write(chip, 10, (127 - chip->dac_volume[4]) | mute);
95 cs4362a_write(chip, 11, (127 - chip->dac_volume[5]) | mute);
96 cs4362a_write(chip, 13, (127 - chip->dac_volume[6]) | mute);
97 cs4362a_write(chip, 14, (127 - chip->dac_volume[7]) | mute);
98} 91}
99 92
100static void update_cs43xx_volume(struct oxygen *chip) 93static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value)
101{ 94{
102 cs4398_write(chip, 5, (127 - chip->dac_volume[0]) * 2); 95 struct xonar_cs43xx *data = chip->model_data;
103 cs4398_write(chip, 6, (127 - chip->dac_volume[1]) * 2); 96
104 update_cs4362a_volumes(chip); 97 oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value);
98 if (reg < ARRAY_SIZE(data->cs4362a_regs))
99 data->cs4362a_regs[reg] = value;
105} 100}
106 101
107static void update_cs43xx_mute(struct oxygen *chip) 102static void cs4362a_write_cached(struct oxygen *chip, u8 reg, u8 value)
108{ 103{
109 u8 reg; 104 struct xonar_cs43xx *data = chip->model_data;
110 105
111 reg = CS4398_MUTEP_LOW | CS4398_PAMUTE; 106 if (value != data->cs4362a_regs[reg])
112 if (chip->dac_mute) 107 cs4362a_write(chip, reg, value);
113 reg |= CS4398_MUTE_B | CS4398_MUTE_A;
114 cs4398_write(chip, 4, reg);
115 update_cs4362a_volumes(chip);
116} 108}
117 109
118static void cs43xx_init(struct oxygen *chip) 110static void cs43xx_registers_init(struct oxygen *chip)
119{ 111{
120 struct xonar_cs43xx *data = chip->model_data; 112 struct xonar_cs43xx *data = chip->model_data;
113 unsigned int i;
121 114
122 /* set CPEN (control port mode) and power down */ 115 /* set CPEN (control port mode) and power down */
123 cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN); 116 cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN);
124 cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN); 117 cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
125 /* configure */ 118 /* configure */
126 cs4398_write(chip, 2, data->cs4398_fm); 119 cs4398_write(chip, 2, data->cs4398_regs[2]);
127 cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L); 120 cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L);
121 cs4398_write(chip, 4, data->cs4398_regs[4]);
122 cs4398_write(chip, 5, data->cs4398_regs[5]);
123 cs4398_write(chip, 6, data->cs4398_regs[6]);
128 cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP | 124 cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP |
129 CS4398_ZERO_CROSS | CS4398_SOFT_RAMP); 125 CS4398_ZERO_CROSS | CS4398_SOFT_RAMP);
130 cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST); 126 cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
@@ -132,11 +128,8 @@ static void cs43xx_init(struct oxygen *chip)
132 CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP); 128 CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP);
133 cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE); 129 cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE);
134 cs4362a_write(chip, 0x05, 0); 130 cs4362a_write(chip, 0x05, 0);
135 cs4362a_write(chip, 0x06, data->cs4362a_fm); 131 for (i = 6; i <= 14; ++i)
136 cs4362a_write(chip, 0x09, data->cs4362a_fm_c); 132 cs4362a_write(chip, i, data->cs4362a_regs[i]);
137 cs4362a_write(chip, 0x0c, data->cs4362a_fm);
138 update_cs43xx_volume(chip);
139 update_cs43xx_mute(chip);
140 /* clear power down */ 133 /* clear power down */
141 cs4398_write(chip, 8, CS4398_CPEN); 134 cs4398_write(chip, 8, CS4398_CPEN);
142 cs4362a_write(chip, 0x01, CS4362A_CPEN); 135 cs4362a_write(chip, 0x01, CS4362A_CPEN);
@@ -148,17 +141,29 @@ static void xonar_d1_init(struct oxygen *chip)
148 141
149 data->generic.anti_pop_delay = 800; 142 data->generic.anti_pop_delay = 800;
150 data->generic.output_enable_bit = GPIO_D1_OUTPUT_ENABLE; 143 data->generic.output_enable_bit = GPIO_D1_OUTPUT_ENABLE;
151 data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST; 144 data->cs4398_regs[2] =
152 data->cs4362a_fm = CS4362A_FM_SINGLE | 145 CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST;
146 data->cs4398_regs[4] = CS4398_MUTEP_LOW |
147 CS4398_MUTE_B | CS4398_MUTE_A | CS4398_PAMUTE;
148 data->cs4398_regs[5] = 60 * 2;
149 data->cs4398_regs[6] = 60 * 2;
150 data->cs4362a_regs[6] = CS4362A_FM_SINGLE |
153 CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; 151 CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
154 data->cs4362a_fm_c = data->cs4362a_fm; 152 data->cs4362a_regs[7] = 60 | CS4362A_MUTE;
153 data->cs4362a_regs[8] = 60 | CS4362A_MUTE;
154 data->cs4362a_regs[9] = data->cs4362a_regs[6];
155 data->cs4362a_regs[10] = 60 | CS4362A_MUTE;
156 data->cs4362a_regs[11] = 60 | CS4362A_MUTE;
157 data->cs4362a_regs[12] = data->cs4362a_regs[6];
158 data->cs4362a_regs[13] = 60 | CS4362A_MUTE;
159 data->cs4362a_regs[14] = 60 | CS4362A_MUTE;
155 160
156 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, 161 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
157 OXYGEN_2WIRE_LENGTH_8 | 162 OXYGEN_2WIRE_LENGTH_8 |
158 OXYGEN_2WIRE_INTERRUPT_MASK | 163 OXYGEN_2WIRE_INTERRUPT_MASK |
159 OXYGEN_2WIRE_SPEED_FAST); 164 OXYGEN_2WIRE_SPEED_FAST);
160 165
161 cs43xx_init(chip); 166 cs43xx_registers_init(chip);
162 167
163 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, 168 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
164 GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE); 169 GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE);
@@ -200,7 +205,7 @@ static void xonar_d1_resume(struct oxygen *chip)
200{ 205{
201 oxygen_set_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC); 206 oxygen_set_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
202 msleep(1); 207 msleep(1);
203 cs43xx_init(chip); 208 cs43xx_registers_init(chip);
204 xonar_enable_output(chip); 209 xonar_enable_output(chip);
205} 210}
206 211
@@ -220,27 +225,56 @@ static void set_cs43xx_params(struct oxygen *chip,
220 cs4398_fm = CS4398_FM_QUAD; 225 cs4398_fm = CS4398_FM_QUAD;
221 cs4362a_fm = CS4362A_FM_QUAD; 226 cs4362a_fm = CS4362A_FM_QUAD;
222 } 227 }
223 data->cs4398_fm = CS4398_DEM_NONE | CS4398_DIF_LJUST | cs4398_fm; 228 cs4398_fm |= CS4398_DEM_NONE | CS4398_DIF_LJUST;
224 data->cs4362a_fm = 229 cs4398_write_cached(chip, 2, cs4398_fm);
225 (data->cs4362a_fm & ~CS4362A_FM_MASK) | cs4362a_fm; 230 cs4362a_fm |= data->cs4362a_regs[6] & ~CS4362A_FM_MASK;
226 data->cs4362a_fm_c = 231 cs4362a_write_cached(chip, 6, cs4362a_fm);
227 (data->cs4362a_fm_c & ~CS4362A_FM_MASK) | cs4362a_fm; 232 cs4362a_write_cached(chip, 12, cs4362a_fm);
228 cs4398_write(chip, 2, data->cs4398_fm); 233 cs4362a_fm &= CS4362A_FM_MASK;
229 cs4362a_write(chip, 0x06, data->cs4362a_fm); 234 cs4362a_fm |= data->cs4362a_regs[9] & ~CS4362A_FM_MASK;
230 cs4362a_write(chip, 0x09, data->cs4362a_fm_c); 235 cs4362a_write_cached(chip, 9, cs4362a_fm);
231 cs4362a_write(chip, 0x0c, data->cs4362a_fm); 236}
237
238static void update_cs4362a_volumes(struct oxygen *chip)
239{
240 unsigned int i;
241 u8 mute;
242
243 mute = chip->dac_mute ? CS4362A_MUTE : 0;
244 for (i = 0; i < 6; ++i)
245 cs4362a_write_cached(chip, 7 + i + i / 2,
246 (127 - chip->dac_volume[2 + i]) | mute);
247}
248
249static void update_cs43xx_volume(struct oxygen *chip)
250{
251 cs4398_write_cached(chip, 5, (127 - chip->dac_volume[0]) * 2);
252 cs4398_write_cached(chip, 6, (127 - chip->dac_volume[1]) * 2);
253 update_cs4362a_volumes(chip);
254}
255
256static void update_cs43xx_mute(struct oxygen *chip)
257{
258 u8 reg;
259
260 reg = CS4398_MUTEP_LOW | CS4398_PAMUTE;
261 if (chip->dac_mute)
262 reg |= CS4398_MUTE_B | CS4398_MUTE_A;
263 cs4398_write_cached(chip, 4, reg);
264 update_cs4362a_volumes(chip);
232} 265}
233 266
234static void update_cs43xx_center_lfe_mix(struct oxygen *chip, bool mixed) 267static void update_cs43xx_center_lfe_mix(struct oxygen *chip, bool mixed)
235{ 268{
236 struct xonar_cs43xx *data = chip->model_data; 269 struct xonar_cs43xx *data = chip->model_data;
270 u8 reg;
237 271
238 data->cs4362a_fm_c &= ~CS4362A_ATAPI_MASK; 272 reg = data->cs4362a_regs[9] & ~CS4362A_ATAPI_MASK;
239 if (mixed) 273 if (mixed)
240 data->cs4362a_fm_c |= CS4362A_ATAPI_B_LR | CS4362A_ATAPI_A_LR; 274 reg |= CS4362A_ATAPI_B_LR | CS4362A_ATAPI_A_LR;
241 else 275 else
242 data->cs4362a_fm_c |= CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; 276 reg |= CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
243 cs4362a_write(chip, 0x09, data->cs4362a_fm_c); 277 cs4362a_write_cached(chip, 9, reg);
244} 278}
245 279
246static const struct snd_kcontrol_new front_panel_switch = { 280static const struct snd_kcontrol_new front_panel_switch = {