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/xonar_cs43xx.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/xonar_cs43xx.c')
-rw-r--r-- | sound/pci/oxygen/xonar_cs43xx.c | 140 |
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 | ||
70 | struct xonar_cs43xx { | 70 | struct 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 | ||
77 | static void cs4398_write(struct oxygen *chip, u8 reg, u8 value) | 76 | static 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 | ||
82 | static 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 | ||
87 | static void update_cs4362a_volumes(struct oxygen *chip) | 85 | static 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 | ||
100 | static void update_cs43xx_volume(struct oxygen *chip) | 93 | static 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 | ||
107 | static void update_cs43xx_mute(struct oxygen *chip) | 102 | static 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 | ||
118 | static void cs43xx_init(struct oxygen *chip) | 110 | static 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 | |||
238 | static 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 | |||
249 | static 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 | |||
256 | static 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 | ||
234 | static void update_cs43xx_center_lfe_mix(struct oxygen *chip, bool mixed) | 267 | static 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 | ||
246 | static const struct snd_kcontrol_new front_panel_switch = { | 280 | static const struct snd_kcontrol_new front_panel_switch = { |