📄 wm8750.c.svn-base
字号:
return 1;#endif } s->i2c_data[s->i2c_len ++] = data; if (s->i2c_len != 2) return 0; cmd = s->i2c_data[0] >> 1; value = ((s->i2c_data[0] << 8) | s->i2c_data[1]) & 0x1ff; switch (cmd) { case WM8750_LADCIN: /* ADC Signal Path Control (Left) */ s->diff[0] = (((value >> 6) & 3) == 3); /* LINSEL */ if (s->diff[0]) s->in[0] = &s->adc_voice[0 + s->ds * 1]; else s->in[0] = &s->adc_voice[((value >> 6) & 3) * 1 + 0]; break; case WM8750_RADCIN: /* ADC Signal Path Control (Right) */ s->diff[1] = (((value >> 6) & 3) == 3); /* RINSEL */ if (s->diff[1]) s->in[1] = &s->adc_voice[0 + s->ds * 1]; else s->in[1] = &s->adc_voice[((value >> 6) & 3) * 1 + 0]; break; case WM8750_ADCIN: /* ADC Input Mode */ s->ds = (value >> 8) & 1; /* DS */ if (s->diff[0]) s->in[0] = &s->adc_voice[0 + s->ds * 1]; if (s->diff[1]) s->in[1] = &s->adc_voice[0 + s->ds * 1]; s->monomix[0] = (value >> 6) & 3; /* MONOMIX */ break; case WM8750_ADCTL1: /* Additional Control (1) */ s->monomix[1] = (value >> 1) & 1; /* DMONOMIX */ break; case WM8750_PWR1: /* Power Management (1) */ s->enable = ((value >> 6) & 7) == 3; /* VMIDSEL, VREF */ wm8750_set_format(s); break; case WM8750_LINVOL: /* Left Channel PGA */ s->invol[0] = value & 0x3f; /* LINVOL */ s->inmute[0] = (value >> 7) & 1; /* LINMUTE */ wm8750_mask_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); break; case WM8750_ADCDAC: /* ADC and DAC Control */ s->pol = (value >> 5) & 3; /* ADCPOL */ s->mute = (value >> 3) & 1; /* DACMU */ wm8750_mask_update(s); break; case WM8750_ADCTL3: /* Additional Control (3) */ break; case WM8750_LADC: /* Left ADC Digital Volume */ s->invol[2] = value & 0xff; /* LADCVOL */ break; case WM8750_RADC: /* Right ADC Digital Volume */ s->invol[3] = value & 0xff; /* RADCVOL */ break; case WM8750_ALC1: /* ALC Control (1) */ s->alc = (value >> 7) & 3; /* ALCSEL */ break; case WM8750_NGATE: /* Noise Gate Control */ case WM8750_3D: /* 3D enhance */ break; case WM8750_LDAC: /* Left Channel Digital Volume */ s->outvol[0] = value & 0xff; /* LDACVOL */ break; case WM8750_RDAC: /* Right Channel Digital Volume */ s->outvol[1] = value & 0xff; /* RDACVOL */ break; case WM8750_BASS: /* Bass Control */ break; case WM8750_LOUTM1: /* Left Mixer Control (1) */ s->path[0] = (value >> 8) & 1; /* LD2LO */ break; case WM8750_LOUTM2: /* Left Mixer Control (2) */ s->path[1] = (value >> 8) & 1; /* RD2LO */ break; case WM8750_ROUTM1: /* Right Mixer Control (1) */ s->path[2] = (value >> 8) & 1; /* LD2RO */ break; case WM8750_ROUTM2: /* Right Mixer Control (2) */ s->path[3] = (value >> 8) & 1; /* RD2RO */ break; case WM8750_MOUTM1: /* Mono Mixer Control (1) */ s->mpath[0] = (value >> 8) & 1; /* LD2MO */ break; case WM8750_MOUTM2: /* Mono Mixer Control (2) */ s->mpath[1] = (value >> 8) & 1; /* RD2MO */ break; case WM8750_LOUT1V: /* LOUT1 Volume */ s->outvol[2] = value & 0x7f; /* LOUT2VOL */ break; case WM8750_LOUT2V: /* LOUT2 Volume */ s->outvol[4] = value & 0x7f; /* LOUT2VOL */ break; case WM8750_ROUT1V: /* ROUT1 Volume */ s->outvol[3] = value & 0x7f; /* ROUT2VOL */ break; case WM8750_ROUT2V: /* ROUT2 Volume */ s->outvol[5] = value & 0x7f; /* ROUT2VOL */ break; case WM8750_MOUTV: /* MONOOUT Volume */ s->outvol[6] = value & 0x7f; /* MONOOUTVOL */ break; case WM8750_ADCTL2: /* Additional Control (2) */ break; case WM8750_PWR2: /* Power Management (2) */ s->power = value & 0x7e; break; case WM8750_IFACE: /* Digital Audio Interface Format */#ifdef VERBOSE if (value & 0x40) /* MS */ printf("%s: attempt to enable Master Mode\n", __FUNCTION__);#endif s->format = value; wm8750_set_format(s); break; case WM8750_SRATE: /* Clocking and Sample Rate Control */ s->rate = &wm_rate_table[(value >> 1) & 0x1f]; wm8750_set_format(s); break; case WM8750_RESET: /* Reset */ wm8750_reset(&s->i2c); break;#ifdef VERBOSE default: printf("%s: unknown register %02x\n", __FUNCTION__, cmd);#endif } return 0;}static int wm8750_rx(i2c_slave *i2c){ return 0x00;}static void wm8750_save(QEMUFile *f, void *opaque){ struct wm8750_s *s = (struct wm8750_s *) opaque; int i; qemu_put_8s(f, &s->i2c_data[0]); qemu_put_8s(f, &s->i2c_data[1]); qemu_put_be32(f, s->i2c_len); qemu_put_be32(f, s->enable); qemu_put_be32(f, s->idx_in); qemu_put_be32(f, s->req_in); qemu_put_be32(f, s->idx_out); qemu_put_be32(f, s->req_out); for (i = 0; i < 7; i ++) qemu_put_8s(f, &s->outvol[i]); for (i = 0; i < 2; i ++) qemu_put_8s(f, &s->outmute[i]); for (i = 0; i < 4; i ++) qemu_put_8s(f, &s->invol[i]); for (i = 0; i < 2; i ++) qemu_put_8s(f, &s->inmute[i]); for (i = 0; i < 2; i ++) qemu_put_8s(f, &s->diff[i]); qemu_put_8s(f, &s->pol); qemu_put_8s(f, &s->ds); for (i = 0; i < 2; i ++) qemu_put_8s(f, &s->monomix[i]); qemu_put_8s(f, &s->alc); qemu_put_8s(f, &s->mute); for (i = 0; i < 4; i ++) qemu_put_8s(f, &s->path[i]); for (i = 0; i < 2; i ++) 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);}static int wm8750_load(QEMUFile *f, void *opaque, int version_id){ struct wm8750_s *s = (struct wm8750_s *) opaque; int i; qemu_get_8s(f, &s->i2c_data[0]); qemu_get_8s(f, &s->i2c_data[1]); s->i2c_len = qemu_get_be32(f); s->enable = qemu_get_be32(f); s->idx_in = qemu_get_be32(f); s->req_in = qemu_get_be32(f); s->idx_out = qemu_get_be32(f); s->req_out = qemu_get_be32(f); for (i = 0; i < 7; i ++) qemu_get_8s(f, &s->outvol[i]); for (i = 0; i < 2; i ++) qemu_get_8s(f, &s->outmute[i]); for (i = 0; i < 4; i ++) qemu_get_8s(f, &s->invol[i]); for (i = 0; i < 2; i ++) qemu_get_8s(f, &s->inmute[i]); for (i = 0; i < 2; i ++) qemu_get_8s(f, &s->diff[i]); qemu_get_8s(f, &s->pol); qemu_get_8s(f, &s->ds); for (i = 0; i < 2; i ++) qemu_get_8s(f, &s->monomix[i]); qemu_get_8s(f, &s->alc); qemu_get_8s(f, &s->mute); for (i = 0; i < 4; i ++) qemu_get_8s(f, &s->path[i]); for (i = 0; i < 2; i ++) 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;}static int wm8750_iid = 0;i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio){ struct wm8750_s *s = (struct wm8750_s *) i2c_slave_init(bus, 0, sizeof(struct wm8750_s)); s->i2c.event = wm8750_event; s->i2c.recv = wm8750_rx; s->i2c.send = wm8750_tx; AUD_register_card(audio, CODEC, &s->card); wm8750_reset(&s->i2c); register_savevm(CODEC, wm8750_iid ++, 0, wm8750_save, wm8750_load, s); return &s->i2c;}static void wm8750_fini(i2c_slave *i2c){ struct wm8750_s *s = (struct wm8750_s *) i2c; wm8750_reset(&s->i2c); AUD_remove_card(&s->card); qemu_free(s);}void wm8750_data_req_set(i2c_slave *i2c, void (*data_req)(void *, int, int), void *opaque){ struct wm8750_s *s = (struct wm8750_s *) i2c; s->data_req = data_req; s->opaque = opaque;}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; s->req_out -= 4; s->idx_out += 4; if (s->idx_out >= sizeof(s->data_out) || s->req_out <= 0) wm8750_out_flush(s);}uint32_t wm8750_adc_dat(void *opaque){ struct wm8750_s *s = (struct wm8750_s *) opaque; uint32_t *data; if (s->idx_in >= sizeof(s->data_in)) wm8750_in_load(s); data = (uint32_t *) &s->data_in[s->idx_in]; s->req_in -= 4; s->idx_in += 4; return *data & s->inmask;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -