diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2009-09-28 05:18:45 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-09-28 05:54:29 -0400 |
commit | 6f0de3ce068e48b033b5e4d0822b47218e9d206c (patch) | |
tree | 6e4e9c054a867e5deee94df181701dedc99e4275 /sound/pci/oxygen/oxygen.c | |
parent | dc0adf48daa81b05765d3c5ebab76321f77e9d21 (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/oxygen.c')
-rw-r--r-- | sound/pci/oxygen/oxygen.c | 107 |
1 files changed, 58 insertions, 49 deletions
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index 53dff7193f31..c986c5ebf65b 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
@@ -97,8 +97,8 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids); | |||
97 | #define GPIO_CLARO_HP 0x0100 | 97 | #define GPIO_CLARO_HP 0x0100 |
98 | 98 | ||
99 | struct generic_data { | 99 | struct generic_data { |
100 | u8 ak4396_ctl2; | 100 | u8 ak4396_regs[4][5]; |
101 | u16 saved_wm8785_registers[2]; | 101 | u16 wm8785_regs[1]; |
102 | }; | 102 | }; |
103 | 103 | ||
104 | static void ak4396_write(struct oxygen *chip, unsigned int codec, | 104 | static void ak4396_write(struct oxygen *chip, unsigned int codec, |
@@ -108,12 +108,24 @@ static void ak4396_write(struct oxygen *chip, unsigned int codec, | |||
108 | static const u8 codec_spi_map[4] = { | 108 | static const u8 codec_spi_map[4] = { |
109 | 0, 1, 2, 4 | 109 | 0, 1, 2, 4 |
110 | }; | 110 | }; |
111 | struct generic_data *data = chip->model_data; | ||
112 | |||
111 | oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | | 113 | oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | |
112 | OXYGEN_SPI_DATA_LENGTH_2 | | 114 | OXYGEN_SPI_DATA_LENGTH_2 | |
113 | OXYGEN_SPI_CLOCK_160 | | 115 | OXYGEN_SPI_CLOCK_160 | |
114 | (codec_spi_map[codec] << OXYGEN_SPI_CODEC_SHIFT) | | 116 | (codec_spi_map[codec] << OXYGEN_SPI_CODEC_SHIFT) | |
115 | OXYGEN_SPI_CEN_LATCH_CLOCK_HI, | 117 | OXYGEN_SPI_CEN_LATCH_CLOCK_HI, |
116 | AK4396_WRITE | (reg << 8) | value); | 118 | AK4396_WRITE | (reg << 8) | value); |
119 | data->ak4396_regs[codec][reg] = value; | ||
120 | } | ||
121 | |||
122 | static void ak4396_write_cached(struct oxygen *chip, unsigned int codec, | ||
123 | u8 reg, u8 value) | ||
124 | { | ||
125 | struct generic_data *data = chip->model_data; | ||
126 | |||
127 | if (value != data->ak4396_regs[codec][reg]) | ||
128 | ak4396_write(chip, codec, reg, value); | ||
117 | } | 129 | } |
118 | 130 | ||
119 | static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value) | 131 | static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value) |
@@ -126,20 +138,8 @@ static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value) | |||
126 | (3 << OXYGEN_SPI_CODEC_SHIFT) | | 138 | (3 << OXYGEN_SPI_CODEC_SHIFT) | |
127 | OXYGEN_SPI_CEN_LATCH_CLOCK_LO, | 139 | OXYGEN_SPI_CEN_LATCH_CLOCK_LO, |
128 | (reg << 9) | value); | 140 | (reg << 9) | value); |
129 | if (reg < ARRAY_SIZE(data->saved_wm8785_registers)) | 141 | if (reg < ARRAY_SIZE(data->wm8785_regs)) |
130 | data->saved_wm8785_registers[reg] = value; | 142 | data->wm8785_regs[reg] = value; |
131 | } | ||
132 | |||
133 | static void update_ak4396_volume(struct oxygen *chip) | ||
134 | { | ||
135 | unsigned int i; | ||
136 | |||
137 | for (i = 0; i < 4; ++i) { | ||
138 | ak4396_write(chip, i, | ||
139 | AK4396_LCH_ATT, chip->dac_volume[i * 2]); | ||
140 | ak4396_write(chip, i, | ||
141 | AK4396_RCH_ATT, chip->dac_volume[i * 2 + 1]); | ||
142 | } | ||
143 | } | 143 | } |
144 | 144 | ||
145 | static void ak4396_registers_init(struct oxygen *chip) | 145 | static void ak4396_registers_init(struct oxygen *chip) |
@@ -148,21 +148,25 @@ static void ak4396_registers_init(struct oxygen *chip) | |||
148 | unsigned int i; | 148 | unsigned int i; |
149 | 149 | ||
150 | for (i = 0; i < 4; ++i) { | 150 | for (i = 0; i < 4; ++i) { |
151 | ak4396_write(chip, i, | 151 | ak4396_write(chip, i, AK4396_CONTROL_1, |
152 | AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); | 152 | AK4396_DIF_24_MSB | AK4396_RSTN); |
153 | ak4396_write(chip, i, | 153 | ak4396_write(chip, i, AK4396_CONTROL_2, |
154 | AK4396_CONTROL_2, data->ak4396_ctl2); | 154 | data->ak4396_regs[0][AK4396_CONTROL_2]); |
155 | ak4396_write(chip, i, | 155 | ak4396_write(chip, i, AK4396_CONTROL_3, |
156 | AK4396_CONTROL_3, AK4396_PCM); | 156 | AK4396_PCM); |
157 | ak4396_write(chip, i, AK4396_LCH_ATT, | ||
158 | chip->dac_volume[i * 2]); | ||
159 | ak4396_write(chip, i, AK4396_RCH_ATT, | ||
160 | chip->dac_volume[i * 2 + 1]); | ||
157 | } | 161 | } |
158 | update_ak4396_volume(chip); | ||
159 | } | 162 | } |
160 | 163 | ||
161 | static void ak4396_init(struct oxygen *chip) | 164 | static void ak4396_init(struct oxygen *chip) |
162 | { | 165 | { |
163 | struct generic_data *data = chip->model_data; | 166 | struct generic_data *data = chip->model_data; |
164 | 167 | ||
165 | data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; | 168 | data->ak4396_regs[0][AK4396_CONTROL_2] = |
169 | AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; | ||
166 | ak4396_registers_init(chip); | 170 | ak4396_registers_init(chip); |
167 | snd_component_add(chip->card, "AK4396"); | 171 | snd_component_add(chip->card, "AK4396"); |
168 | } | 172 | } |
@@ -179,17 +183,15 @@ static void wm8785_registers_init(struct oxygen *chip) | |||
179 | struct generic_data *data = chip->model_data; | 183 | struct generic_data *data = chip->model_data; |
180 | 184 | ||
181 | wm8785_write(chip, WM8785_R7, 0); | 185 | wm8785_write(chip, WM8785_R7, 0); |
182 | wm8785_write(chip, WM8785_R0, data->saved_wm8785_registers[0]); | 186 | wm8785_write(chip, WM8785_R0, data->wm8785_regs[0]); |
183 | wm8785_write(chip, WM8785_R1, data->saved_wm8785_registers[1]); | ||
184 | } | 187 | } |
185 | 188 | ||
186 | static void wm8785_init(struct oxygen *chip) | 189 | static void wm8785_init(struct oxygen *chip) |
187 | { | 190 | { |
188 | struct generic_data *data = chip->model_data; | 191 | struct generic_data *data = chip->model_data; |
189 | 192 | ||
190 | data->saved_wm8785_registers[0] = WM8785_MCR_SLAVE | | 193 | data->wm8785_regs[0] = |
191 | WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST; | 194 | WM8785_MCR_SLAVE | WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST; |
192 | data->saved_wm8785_registers[1] = WM8785_WL_24; | ||
193 | wm8785_registers_init(chip); | 195 | wm8785_registers_init(chip); |
194 | snd_component_add(chip->card, "WM8785"); | 196 | snd_component_add(chip->card, "WM8785"); |
195 | } | 197 | } |
@@ -270,24 +272,36 @@ static void set_ak4396_params(struct oxygen *chip, | |||
270 | unsigned int i; | 272 | unsigned int i; |
271 | u8 value; | 273 | u8 value; |
272 | 274 | ||
273 | value = data->ak4396_ctl2 & ~AK4396_DFS_MASK; | 275 | value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_DFS_MASK; |
274 | if (params_rate(params) <= 54000) | 276 | if (params_rate(params) <= 54000) |
275 | value |= AK4396_DFS_NORMAL; | 277 | value |= AK4396_DFS_NORMAL; |
276 | else if (params_rate(params) <= 108000) | 278 | else if (params_rate(params) <= 108000) |
277 | value |= AK4396_DFS_DOUBLE; | 279 | value |= AK4396_DFS_DOUBLE; |
278 | else | 280 | else |
279 | value |= AK4396_DFS_QUAD; | 281 | value |= AK4396_DFS_QUAD; |
280 | data->ak4396_ctl2 = value; | ||
281 | 282 | ||
282 | msleep(1); /* wait for the new MCLK to become stable */ | 283 | msleep(1); /* wait for the new MCLK to become stable */ |
283 | 284 | ||
285 | if (value != data->ak4396_regs[0][AK4396_CONTROL_2]) { | ||
286 | for (i = 0; i < 4; ++i) { | ||
287 | ak4396_write(chip, i, AK4396_CONTROL_1, | ||
288 | AK4396_DIF_24_MSB); | ||
289 | ak4396_write(chip, i, AK4396_CONTROL_2, value); | ||
290 | ak4396_write(chip, i, AK4396_CONTROL_1, | ||
291 | AK4396_DIF_24_MSB | AK4396_RSTN); | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | static void update_ak4396_volume(struct oxygen *chip) | ||
297 | { | ||
298 | unsigned int i; | ||
299 | |||
284 | for (i = 0; i < 4; ++i) { | 300 | for (i = 0; i < 4; ++i) { |
285 | ak4396_write(chip, i, | 301 | ak4396_write_cached(chip, i, AK4396_LCH_ATT, |
286 | AK4396_CONTROL_1, AK4396_DIF_24_MSB); | 302 | chip->dac_volume[i * 2]); |
287 | ak4396_write(chip, i, | 303 | ak4396_write_cached(chip, i, AK4396_RCH_ATT, |
288 | AK4396_CONTROL_2, value); | 304 | chip->dac_volume[i * 2 + 1]); |
289 | ak4396_write(chip, i, | ||
290 | AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); | ||
291 | } | 305 | } |
292 | } | 306 | } |
293 | 307 | ||
@@ -297,21 +311,19 @@ static void update_ak4396_mute(struct oxygen *chip) | |||
297 | unsigned int i; | 311 | unsigned int i; |
298 | u8 value; | 312 | u8 value; |
299 | 313 | ||
300 | value = data->ak4396_ctl2 & ~AK4396_SMUTE; | 314 | value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_SMUTE; |
301 | if (chip->dac_mute) | 315 | if (chip->dac_mute) |
302 | value |= AK4396_SMUTE; | 316 | value |= AK4396_SMUTE; |
303 | data->ak4396_ctl2 = value; | ||
304 | for (i = 0; i < 4; ++i) | 317 | for (i = 0; i < 4; ++i) |
305 | ak4396_write(chip, i, AK4396_CONTROL_2, value); | 318 | ak4396_write_cached(chip, i, AK4396_CONTROL_2, value); |
306 | } | 319 | } |
307 | 320 | ||
308 | static void set_wm8785_params(struct oxygen *chip, | 321 | static void set_wm8785_params(struct oxygen *chip, |
309 | struct snd_pcm_hw_params *params) | 322 | struct snd_pcm_hw_params *params) |
310 | { | 323 | { |
324 | struct generic_data *data = chip->model_data; | ||
311 | unsigned int value; | 325 | unsigned int value; |
312 | 326 | ||
313 | wm8785_write(chip, WM8785_R7, 0); | ||
314 | |||
315 | value = WM8785_MCR_SLAVE | WM8785_FORMAT_LJUST; | 327 | value = WM8785_MCR_SLAVE | WM8785_FORMAT_LJUST; |
316 | if (params_rate(params) <= 48000) | 328 | if (params_rate(params) <= 48000) |
317 | value |= WM8785_OSR_SINGLE; | 329 | value |= WM8785_OSR_SINGLE; |
@@ -319,13 +331,10 @@ static void set_wm8785_params(struct oxygen *chip, | |||
319 | value |= WM8785_OSR_DOUBLE; | 331 | value |= WM8785_OSR_DOUBLE; |
320 | else | 332 | else |
321 | value |= WM8785_OSR_QUAD; | 333 | value |= WM8785_OSR_QUAD; |
322 | wm8785_write(chip, WM8785_R0, value); | 334 | if (value != data->wm8785_regs[0]) { |
323 | 335 | wm8785_write(chip, WM8785_R7, 0); | |
324 | if (snd_pcm_format_width(params_format(params)) <= 16) | 336 | wm8785_write(chip, WM8785_R0, value); |
325 | value = WM8785_WL_16; | 337 | } |
326 | else | ||
327 | value = WM8785_WL_24; | ||
328 | wm8785_write(chip, WM8785_R1, value); | ||
329 | } | 338 | } |
330 | 339 | ||
331 | static void set_ak5385_params(struct oxygen *chip, | 340 | static void set_ak5385_params(struct oxygen *chip, |