[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/2] wm8570: switch to generic volume control v2
From: |
Jan Kiszka |
Subject: |
[Qemu-devel] [PATCH 2/2] wm8570: switch to generic volume control v2 |
Date: |
Fri, 02 May 2008 21:05:19 +0200 |
User-agent: |
Thunderbird 2.0.0.12 (X11/20080226) |
Make use of AUD_set_volume_in/out for muting and OUT2V, drop all
internally applied mute masks. Avoids 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, and the AUD
layer is not yet supporting it anyway.
Signed-off-by: Jan Kiszka <address@hidden>
---
hw/wm8750.c | 55 +++++++++++++++++++++++++++----------------------------
1 file changed, 27 insertions(+), 28 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;
@@ -125,6 +131,16 @@ static const struct wm_rate_s wm_rate_ta
{ 192, 88200, 192, 88200 }, /* SR: 11111 */
};
+static void wm8750_vol_update(struct wm8750_s *s)
+{
+ AUD_set_volume_in(*s->in[0], s->mute,
+ s->inmute[0] ? 0 : 0xff,
+ s->inmute[1] ? 0 : 0xff);
+ AUD_set_volume_out(*s->out[0], 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]);
+}
+
static void wm8750_set_format(struct wm8750_s *s)
{
int i;
@@ -185,6 +201,8 @@ static void wm8750_set_format(struct wm8
CODEC ".monomix", s, wm8750_audio_out_cb, &out_fmt);
/* no sense emulating OUT3 which is a mix of other outputs */
+ wm8750_vol_update(s);
+
/* We should connect the left and right channels to their
* respective inputs/outputs but we have completely no need
* for mixing or combining paths to different ports, so we
@@ -195,22 +213,6 @@ 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)
-{
-#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);
-}
-
void wm8750_reset(i2c_slave *i2c)
{
struct wm8750_s *s = (struct wm8750_s *) i2c;
@@ -249,7 +251,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 +369,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 +444,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 +453,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 +535,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 +575,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 +619,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 +653,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;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH 2/2] wm8570: switch to generic volume control v2,
Jan Kiszka <=