* [Qemu-devel] [PATCH 2/2] wm8570: switch to generic volume control
@ 2008-04-27 11:27 Jan Kiszka
0 siblings, 0 replies; only message in thread
From: Jan Kiszka @ 2008-04-27 11:27 UTC (permalink / raw)
To: qemu-devel
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 <jan.kiszka@web.de>
---
hw/wm8750.c | 47 ++++++++++++++++++++++-------------------------
1 file changed, 22 insertions(+), 25 deletions(-)
Index: b/hw/wm8750.c
===================================================================
--- a/hw/wm8750.c
+++ b/hw/wm8750.c
@@ -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 wm8
AUD_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, uin
case 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, uin
case 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, uin
case 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, voi
qemu_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, void
qemu_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;
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2008-04-27 11:27 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-04-27 11:27 [Qemu-devel] [PATCH 2/2] wm8570: switch to generic volume control Jan Kiszka
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.