wm8570: switch to generic volume control
PATCH 2/2 wm8570: switch to generic volume control
Make use of AUD_set_volume for muting and OUT2V, drop all internally applied mute masks. Note that - this time - I avoid pow() in favor of a look-up table.
Successfully tested with the MusicPal. Line-in volume control still needs to be added, I'm lacking an appropriate test case.
Signed-off-by Jan Kiszka <[email protected]>
--- hw/wm8750.c | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-)
hw/wm8750.c +22 -25
@@ -39,10 +39,16 @@ struct wm8750_s {uint8_t diff[2 ], pol, ds, monomix[2 ], alc, mute;uint8_t path[4 ], mpath[2 ], power, format; -uint32_t inmask, outmask;const struct wm_rate_s *rate; }; +/* pow(10.0, -i / 20.0), i = 0..42 */ +static const uint8_t vol_db_table[] = { +255 ,227 ,203 ,181 ,161 ,143 ,128 ,114 ,102 ,90 ,81 ,72 ,64 ,57 ,51 ,45 , +40 ,36 ,32 ,29 ,26 ,23 ,20 ,18 ,16 ,14 ,13 ,11 ,10 ,9 ,8 ,7 ,6 ,6 ,5 ,5 , +4 ,4 ,3 ,3 ,3 ,2 ,2 +}; +static inline void wm8750_in_load (struct wm8750_s *s) {int acquired;
@@ -195,20 +201,14 @@ static void wm8750_set_format(struct wm8AUD_set_active_out (*s->out[0 ],1 ); } -static void inline wm8750_mask_update (struct wm8750_s *s) +static void inline wm8750_vol_update (struct wm8750_s *s) { -#define R_ONLY 0x0000ffff -#define L_ONLY 0xffff0000 -#define BOTH (R_ONLY | L_ONLY) -#define NONE (R_ONLY & L_ONLY) - s->inmask = - (s->inmute[0 ] ?R_ONLY :BOTH ) & - (s->inmute[1 ] ?L_ONLY :BOTH ) & - (s->mute ?NONE :BOTH ); - s->outmask = - (s->outmute[0 ] ?R_ONLY :BOTH ) & - (s->outmute[1 ] ?L_ONLY :BOTH ) & - (s->mute ?NONE :BOTH ); +AUD_set_volume (AUD_MIXER_LINE_IN , s->mute, + s->inmute[0 ] ?0 :0xff , + s->inmute[1 ] ?0 :0xff ); +AUD_set_volume (AUD_MIXER_PCM_OUT , s->mute, + s->outmute[0 ] ?0 : vol_db_table[(0x7f -s->outvol[4 ])/3 ], + s->outmute[1 ] ?0 : vol_db_table[(0x7f -s->outvol[5 ])/3 ]); }void wm8750_reset (i2c_slave *i2c)
@@ -249,7 +249,7 @@ void wm8750_reset(i2c_slave *i2c) s->req_in =0 ; s->idx_out =0 ; s->req_out =0 ; -wm8750_mask_update (s); +wm8750_vol_update (s); s->i2c_len =0 ; }
@@ -367,19 +367,19 @@ static int wm8750_tx(i2c_slave *i2c, uincase WM8750_LINVOL :/* Left Channel PGA */ s->invol[0 ] = value &0x3f ;/* LINVOL */ s->inmute[0 ] = (value >>7 ) &1 ;/* LINMUTE */ -wm8750_mask_update (s); +wm8750_vol_update (s);break ;case WM8750_RINVOL :/* Right Channel PGA */ s->invol[1 ] = value &0x3f ;/* RINVOL */ s->inmute[1 ] = (value >>7 ) &1 ;/* RINMUTE */ -wm8750_mask_update (s); +wm8750_vol_update (s);break ;case WM8750_ADCDAC :/* ADC and DAC Control */ s->pol = (value >>5 ) &3 ;/* ADCPOL */ s->mute = (value >>3 ) &1 ;/* DACMU */ -wm8750_mask_update (s); +wm8750_vol_update (s);break ;case WM8750_ADCTL3 :/* Additional Control (3) */
@@ -442,6 +442,7 @@ static int wm8750_tx(i2c_slave *i2c, uincase WM8750_LOUT2V :/* LOUT2 Volume */ s->outvol[4 ] = value &0x7f ;/* LOUT2VOL */ +wm8750_vol_update (s);break ;case WM8750_ROUT1V :/* ROUT1 Volume */
@@ -450,6 +451,7 @@ static int wm8750_tx(i2c_slave *i2c, uincase WM8750_ROUT2V :/* ROUT2 Volume */ s->outvol[5 ] = value &0x7f ;/* ROUT2VOL */ +wm8750_vol_update (s);break ;case WM8750_MOUTV :/* MONOOUT Volume */
@@ -531,8 +533,6 @@ static void wm8750_save(QEMUFile *f, voiqemu_put_8s (f, &s->mpath[i]);qemu_put_8s (f, &s->format);qemu_put_8s (f, &s->power); -qemu_put_be32s (f, &s->inmask); -qemu_put_be32s (f, &s->outmask);qemu_put_byte (f, (s->rate - wm_rate_table) /sizeof (*s->rate));i2c_slave_save (f, &s->i2c); }
@@ -573,8 +573,6 @@ static int wm8750_load(QEMUFile *f, voidqemu_get_8s (f, &s->mpath[i]);qemu_get_8s (f, &s->format);qemu_get_8s (f, &s->power); -qemu_get_be32s (f, &s->inmask); -qemu_get_be32s (f, &s->outmask); s->rate = &wm_rate_table[(uint8_t )qemu_get_byte (f) &0x1f ];i2c_slave_load (f, &s->i2c);return 0 ;
@@ -619,8 +617,7 @@ void wm8750_data_req_set(i2c_slave *i2c,void wm8750_dac_dat (void *opaque,uint32_t sample) {struct wm8750_s *s = (struct wm8750_s *) opaque; -uint32_t *data = (uint32_t *) &s->data_out[s->idx_out]; - *data = sample & s->outmask; + *(uint32_t *) &s->data_out[s->idx_out] = sample; s->req_out -=4 ; s->idx_out +=4 ;if (s->idx_out >=sizeof (s->data_out) || s->req_out <=0 )
@@ -654,5 +651,5 @@ uint32_t wm8750_adc_dat(void *opaque) data = (uint32_t *) &s->data_in[s->idx_in]; s->req_in -=4 ; s->idx_in +=4 ; -return *data & s->inmask; +return *data; }