xref: /openbmc/qemu/hw/audio/hda-codec.c (revision a7b7953d)
1 /*
2  * Copyright (C) 2010 Red Hat, Inc.
3  *
4  * written by Gerd Hoffmann <kraxel@redhat.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 or
9  * (at your option) version 3 of the License.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "qemu/osdep.h"
21 #include "hw/pci/pci.h"
22 #include "hw/qdev-properties.h"
23 #include "intel-hda.h"
24 #include "migration/vmstate.h"
25 #include "qemu/host-utils.h"
26 #include "qemu/module.h"
27 #include "intel-hda-defs.h"
28 #include "audio/audio.h"
29 #include "trace.h"
30 #include "qom/object.h"
31 
32 /* -------------------------------------------------------------------------- */
33 
34 typedef struct desc_param {
35     uint32_t id;
36     uint32_t val;
37 } desc_param;
38 
39 typedef struct desc_node {
40     uint32_t nid;
41     const char *name;
42     const desc_param *params;
43     uint32_t nparams;
44     uint32_t config;
45     uint32_t pinctl;
46     uint32_t *conn;
47     uint32_t stindex;
48 } desc_node;
49 
50 typedef struct desc_codec {
51     const char *name;
52     uint32_t iid;
53     const desc_node *nodes;
54     uint32_t nnodes;
55 } desc_codec;
56 
hda_codec_find_param(const desc_node * node,uint32_t id)57 static const desc_param* hda_codec_find_param(const desc_node *node, uint32_t id)
58 {
59     int i;
60 
61     for (i = 0; i < node->nparams; i++) {
62         if (node->params[i].id == id) {
63             return &node->params[i];
64         }
65     }
66     return NULL;
67 }
68 
hda_codec_find_node(const desc_codec * codec,uint32_t nid)69 static const desc_node* hda_codec_find_node(const desc_codec *codec, uint32_t nid)
70 {
71     int i;
72 
73     for (i = 0; i < codec->nnodes; i++) {
74         if (codec->nodes[i].nid == nid) {
75             return &codec->nodes[i];
76         }
77     }
78     return NULL;
79 }
80 
hda_codec_parse_fmt(uint32_t format,struct audsettings * as)81 static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
82 {
83     if (format & AC_FMT_TYPE_NON_PCM) {
84         return;
85     }
86 
87     as->freq = (format & AC_FMT_BASE_44K) ? 44100 : 48000;
88 
89     switch ((format & AC_FMT_MULT_MASK) >> AC_FMT_MULT_SHIFT) {
90     case 1: as->freq *= 2; break;
91     case 2: as->freq *= 3; break;
92     case 3: as->freq *= 4; break;
93     }
94 
95     switch ((format & AC_FMT_DIV_MASK) >> AC_FMT_DIV_SHIFT) {
96     case 1: as->freq /= 2; break;
97     case 2: as->freq /= 3; break;
98     case 3: as->freq /= 4; break;
99     case 4: as->freq /= 5; break;
100     case 5: as->freq /= 6; break;
101     case 6: as->freq /= 7; break;
102     case 7: as->freq /= 8; break;
103     }
104 
105     switch (format & AC_FMT_BITS_MASK) {
106     case AC_FMT_BITS_8:  as->fmt = AUDIO_FORMAT_S8;  break;
107     case AC_FMT_BITS_16: as->fmt = AUDIO_FORMAT_S16; break;
108     case AC_FMT_BITS_32: as->fmt = AUDIO_FORMAT_S32; break;
109     }
110 
111     as->nchannels = ((format & AC_FMT_CHAN_MASK) >> AC_FMT_CHAN_SHIFT) + 1;
112 }
113 
114 /* -------------------------------------------------------------------------- */
115 /*
116  * HDA codec descriptions
117  */
118 
119 /* some defines */
120 
121 #define QEMU_HDA_ID_VENDOR  0x1af4
122 #define QEMU_HDA_PCM_FORMATS (AC_SUPPCM_BITS_16 |       \
123                               0x1fc /* 16 -> 96 kHz */)
124 #define QEMU_HDA_AMP_NONE    (0)
125 #define QEMU_HDA_AMP_STEPS   0x4a
126 
127 #define   PARAM mixemu
128 #define   HDA_MIXER
129 #include "hda-codec-common.h"
130 
131 #define   PARAM nomixemu
132 #include  "hda-codec-common.h"
133 
134 #define HDA_TIMER_TICKS (SCALE_MS)
135 #define B_SIZE sizeof(st->buf)
136 #define B_MASK (sizeof(st->buf) - 1)
137 
138 /* -------------------------------------------------------------------------- */
139 
140 static const char *fmt2name[] = {
141     [ AUDIO_FORMAT_U8  ] = "PCM-U8",
142     [ AUDIO_FORMAT_S8  ] = "PCM-S8",
143     [ AUDIO_FORMAT_U16 ] = "PCM-U16",
144     [ AUDIO_FORMAT_S16 ] = "PCM-S16",
145     [ AUDIO_FORMAT_U32 ] = "PCM-U32",
146     [ AUDIO_FORMAT_S32 ] = "PCM-S32",
147 };
148 
149 #define TYPE_HDA_AUDIO "hda-audio"
150 OBJECT_DECLARE_SIMPLE_TYPE(HDAAudioState, HDA_AUDIO)
151 
152 typedef struct HDAAudioStream HDAAudioStream;
153 
154 struct HDAAudioStream {
155     HDAAudioState *state;
156     const desc_node *node;
157     bool output, running;
158     uint32_t stream;
159     uint32_t channel;
160     uint32_t format;
161     uint32_t gain_left, gain_right;
162     bool mute_left, mute_right;
163     struct audsettings as;
164     union {
165         SWVoiceIn *in;
166         SWVoiceOut *out;
167     } voice;
168     uint8_t compat_buf[HDA_BUFFER_SIZE];
169     uint32_t compat_bpos;
170     uint8_t buf[8192]; /* size must be power of two */
171     int64_t rpos;
172     int64_t wpos;
173     QEMUTimer *buft;
174     int64_t buft_start;
175 };
176 
177 struct HDAAudioState {
178     HDACodecDevice hda;
179     const char *name;
180 
181     QEMUSoundCard card;
182     const desc_codec *desc;
183     HDAAudioStream st[4];
184     bool running_compat[16];
185     bool running_real[2 * 16];
186 
187     /* properties */
188     uint32_t debug;
189     bool     mixer;
190     bool     use_timer;
191 };
192 
hda_bytes_per_second(HDAAudioStream * st)193 static inline uint32_t hda_bytes_per_second(HDAAudioStream *st)
194 {
195     return 2 * (uint32_t)st->as.nchannels * (uint32_t)st->as.freq;
196 }
197 
hda_timer_sync_adjust(HDAAudioStream * st,int64_t target_pos)198 static inline void hda_timer_sync_adjust(HDAAudioStream *st, int64_t target_pos)
199 {
200     int64_t limit = B_SIZE / 8;
201     int64_t corr = 0;
202 
203     if (target_pos > limit) {
204         corr = HDA_TIMER_TICKS;
205     }
206     if (target_pos < -limit) {
207         corr = -HDA_TIMER_TICKS;
208     }
209     if (target_pos < -(2 * limit)) {
210         corr = -(4 * HDA_TIMER_TICKS);
211     }
212     if (corr == 0) {
213         return;
214     }
215 
216     trace_hda_audio_adjust(st->node->name, target_pos);
217     st->buft_start += corr;
218 }
219 
hda_audio_input_timer(void * opaque)220 static void hda_audio_input_timer(void *opaque)
221 {
222     HDAAudioStream *st = opaque;
223 
224     int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
225 
226     int64_t uptime = now - st->buft_start;
227     int64_t wpos = st->wpos;
228     int64_t rpos = st->rpos;
229     int64_t wanted_rpos;
230 
231     if (uptime <= 0) {
232         /* wanted_rpos <= 0 */
233         goto out_timer;
234     }
235 
236     wanted_rpos = muldiv64(uptime, hda_bytes_per_second(st),
237                            NANOSECONDS_PER_SECOND);
238     wanted_rpos &= -4; /* IMPORTANT! clip to frames */
239 
240     if (wanted_rpos <= rpos) {
241         /* we already transmitted the data */
242         goto out_timer;
243     }
244 
245     int64_t to_transfer = MIN(wpos - rpos, wanted_rpos - rpos);
246     while (to_transfer) {
247         uint32_t start = (rpos & B_MASK);
248         uint32_t chunk = MIN(B_SIZE - start, to_transfer);
249         int rc = hda_codec_xfer(
250                 &st->state->hda, st->stream, false, st->buf + start, chunk);
251         if (!rc) {
252             break;
253         }
254         rpos += chunk;
255         to_transfer -= chunk;
256         st->rpos += chunk;
257     }
258 
259 out_timer:
260 
261     if (st->running) {
262         timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS);
263     }
264 }
265 
hda_audio_input_cb(void * opaque,int avail)266 static void hda_audio_input_cb(void *opaque, int avail)
267 {
268     HDAAudioStream *st = opaque;
269 
270     int64_t wpos = st->wpos;
271     int64_t rpos = st->rpos;
272 
273     int64_t to_transfer = MIN(B_SIZE - (wpos - rpos), avail);
274 
275     while (to_transfer) {
276         uint32_t start = (uint32_t) (wpos & B_MASK);
277         uint32_t chunk = (uint32_t) MIN(B_SIZE - start, to_transfer);
278         uint32_t read = AUD_read(st->voice.in, st->buf + start, chunk);
279         wpos += read;
280         to_transfer -= read;
281         st->wpos += read;
282         if (chunk != read) {
283             break;
284         }
285     }
286 
287     hda_timer_sync_adjust(st, -((wpos - rpos) - (B_SIZE >> 1)));
288 }
289 
hda_audio_output_timer(void * opaque)290 static void hda_audio_output_timer(void *opaque)
291 {
292     HDAAudioStream *st = opaque;
293 
294     int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
295 
296     int64_t uptime = now - st->buft_start;
297     int64_t wpos = st->wpos;
298     int64_t rpos = st->rpos;
299     int64_t wanted_wpos;
300 
301     if (uptime <= 0) {
302         /* wanted_wpos <= 0 */
303         goto out_timer;
304     }
305 
306     wanted_wpos = muldiv64(uptime, hda_bytes_per_second(st),
307                            NANOSECONDS_PER_SECOND);
308     wanted_wpos &= -4; /* IMPORTANT! clip to frames */
309 
310     if (wanted_wpos <= wpos) {
311         /* we already received the data */
312         goto out_timer;
313     }
314 
315     int64_t to_transfer = MIN(B_SIZE - (wpos - rpos), wanted_wpos - wpos);
316     while (to_transfer) {
317         uint32_t start = (wpos & B_MASK);
318         uint32_t chunk = MIN(B_SIZE - start, to_transfer);
319         int rc = hda_codec_xfer(
320                 &st->state->hda, st->stream, true, st->buf + start, chunk);
321         if (!rc) {
322             break;
323         }
324         wpos += chunk;
325         to_transfer -= chunk;
326         st->wpos += chunk;
327     }
328 
329 out_timer:
330 
331     if (st->running) {
332         timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS);
333     }
334 }
335 
hda_audio_output_cb(void * opaque,int avail)336 static void hda_audio_output_cb(void *opaque, int avail)
337 {
338     HDAAudioStream *st = opaque;
339 
340     int64_t wpos = st->wpos;
341     int64_t rpos = st->rpos;
342 
343     int64_t to_transfer = MIN(wpos - rpos, avail);
344 
345     if (wpos - rpos == B_SIZE) {
346         /* drop buffer, reset timer adjust */
347         st->rpos = 0;
348         st->wpos = 0;
349         st->buft_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
350         trace_hda_audio_overrun(st->node->name);
351         return;
352     }
353 
354     while (to_transfer) {
355         uint32_t start = (uint32_t) (rpos & B_MASK);
356         uint32_t chunk = (uint32_t) MIN(B_SIZE - start, to_transfer);
357         uint32_t written = AUD_write(st->voice.out, st->buf + start, chunk);
358         rpos += written;
359         to_transfer -= written;
360         st->rpos += written;
361         if (chunk != written) {
362             break;
363         }
364     }
365 
366     hda_timer_sync_adjust(st, (wpos - rpos) - (B_SIZE >> 1));
367 }
368 
hda_audio_compat_input_cb(void * opaque,int avail)369 static void hda_audio_compat_input_cb(void *opaque, int avail)
370 {
371     HDAAudioStream *st = opaque;
372     int recv = 0;
373     int len;
374     bool rc;
375 
376     while (avail - recv >= sizeof(st->compat_buf)) {
377         if (st->compat_bpos != sizeof(st->compat_buf)) {
378             len = AUD_read(st->voice.in, st->compat_buf + st->compat_bpos,
379                            sizeof(st->compat_buf) - st->compat_bpos);
380             st->compat_bpos += len;
381             recv += len;
382             if (st->compat_bpos != sizeof(st->compat_buf)) {
383                 break;
384             }
385         }
386         rc = hda_codec_xfer(&st->state->hda, st->stream, false,
387                             st->compat_buf, sizeof(st->compat_buf));
388         if (!rc) {
389             break;
390         }
391         st->compat_bpos = 0;
392     }
393 }
394 
hda_audio_compat_output_cb(void * opaque,int avail)395 static void hda_audio_compat_output_cb(void *opaque, int avail)
396 {
397     HDAAudioStream *st = opaque;
398     int sent = 0;
399     int len;
400     bool rc;
401 
402     while (avail - sent >= sizeof(st->compat_buf)) {
403         if (st->compat_bpos == sizeof(st->compat_buf)) {
404             rc = hda_codec_xfer(&st->state->hda, st->stream, true,
405                                 st->compat_buf, sizeof(st->compat_buf));
406             if (!rc) {
407                 break;
408             }
409             st->compat_bpos = 0;
410         }
411         len = AUD_write(st->voice.out, st->compat_buf + st->compat_bpos,
412                         sizeof(st->compat_buf) - st->compat_bpos);
413         st->compat_bpos += len;
414         sent += len;
415         if (st->compat_bpos != sizeof(st->compat_buf)) {
416             break;
417         }
418     }
419 }
420 
hda_audio_set_running(HDAAudioStream * st,bool running)421 static void hda_audio_set_running(HDAAudioStream *st, bool running)
422 {
423     if (st->node == NULL) {
424         return;
425     }
426     if (st->running == running) {
427         return;
428     }
429     st->running = running;
430     trace_hda_audio_running(st->node->name, st->stream, st->running);
431     if (st->state->use_timer) {
432         if (running) {
433             int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
434             st->rpos = 0;
435             st->wpos = 0;
436             st->buft_start = now;
437             timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS);
438         } else {
439             timer_del(st->buft);
440         }
441     }
442     if (st->output) {
443         AUD_set_active_out(st->voice.out, st->running);
444     } else {
445         AUD_set_active_in(st->voice.in, st->running);
446     }
447 }
448 
hda_audio_set_amp(HDAAudioStream * st)449 static void hda_audio_set_amp(HDAAudioStream *st)
450 {
451     bool muted;
452     uint32_t left, right;
453 
454     if (st->node == NULL) {
455         return;
456     }
457 
458     muted = st->mute_left && st->mute_right;
459     left  = st->mute_left  ? 0 : st->gain_left;
460     right = st->mute_right ? 0 : st->gain_right;
461 
462     left = left * 255 / QEMU_HDA_AMP_STEPS;
463     right = right * 255 / QEMU_HDA_AMP_STEPS;
464 
465     if (!st->state->mixer) {
466         return;
467     }
468     if (st->output) {
469         AUD_set_volume_out(st->voice.out, muted, left, right);
470     } else {
471         AUD_set_volume_in(st->voice.in, muted, left, right);
472     }
473 }
474 
hda_audio_setup(HDAAudioStream * st)475 static void hda_audio_setup(HDAAudioStream *st)
476 {
477     bool use_timer = st->state->use_timer;
478     audio_callback_fn cb;
479 
480     if (st->node == NULL) {
481         return;
482     }
483 
484     trace_hda_audio_format(st->node->name, st->as.nchannels,
485                            fmt2name[st->as.fmt], st->as.freq);
486 
487     if (st->output) {
488         if (use_timer) {
489             cb = hda_audio_output_cb;
490             timer_del(st->buft);
491         } else {
492             cb = hda_audio_compat_output_cb;
493         }
494         st->voice.out = AUD_open_out(&st->state->card, st->voice.out,
495                                      st->node->name, st, cb, &st->as);
496     } else {
497         if (use_timer) {
498             cb = hda_audio_input_cb;
499             timer_del(st->buft);
500         } else {
501             cb = hda_audio_compat_input_cb;
502         }
503         st->voice.in = AUD_open_in(&st->state->card, st->voice.in,
504                                    st->node->name, st, cb, &st->as);
505     }
506 }
507 
hda_audio_command(HDACodecDevice * hda,uint32_t nid,uint32_t data)508 static void hda_audio_command(HDACodecDevice *hda, uint32_t nid, uint32_t data)
509 {
510     HDAAudioState *a = HDA_AUDIO(hda);
511     HDAAudioStream *st;
512     const desc_node *node = NULL;
513     const desc_param *param;
514     uint32_t verb, payload, response, count, shift;
515 
516     if ((data & 0x70000) == 0x70000) {
517         /* 12/8 id/payload */
518         verb = (data >> 8) & 0xfff;
519         payload = data & 0x00ff;
520     } else {
521         /* 4/16 id/payload */
522         verb = (data >> 8) & 0xf00;
523         payload = data & 0xffff;
524     }
525 
526     node = hda_codec_find_node(a->desc, nid);
527     if (node == NULL) {
528         goto fail;
529     }
530     dprint(a, 2, "%s: nid %d (%s), verb 0x%x, payload 0x%x\n",
531            __func__, nid, node->name, verb, payload);
532 
533     switch (verb) {
534     /* all nodes */
535     case AC_VERB_PARAMETERS:
536         param = hda_codec_find_param(node, payload);
537         if (param == NULL) {
538             goto fail;
539         }
540         hda_codec_response(hda, true, param->val);
541         break;
542     case AC_VERB_GET_SUBSYSTEM_ID:
543         hda_codec_response(hda, true, a->desc->iid);
544         break;
545 
546     /* all functions */
547     case AC_VERB_GET_CONNECT_LIST:
548         param = hda_codec_find_param(node, AC_PAR_CONNLIST_LEN);
549         count = param ? param->val : 0;
550         response = 0;
551         shift = 0;
552         while (payload < count && shift < 32) {
553             response |= node->conn[payload] << shift;
554             payload++;
555             shift += 8;
556         }
557         hda_codec_response(hda, true, response);
558         break;
559 
560     /* pin widget */
561     case AC_VERB_GET_CONFIG_DEFAULT:
562         hda_codec_response(hda, true, node->config);
563         break;
564     case AC_VERB_GET_PIN_WIDGET_CONTROL:
565         hda_codec_response(hda, true, node->pinctl);
566         break;
567     case AC_VERB_SET_PIN_WIDGET_CONTROL:
568         if (node->pinctl != payload) {
569             dprint(a, 1, "unhandled pin control bit\n");
570         }
571         hda_codec_response(hda, true, 0);
572         break;
573 
574     /* audio in/out widget */
575     case AC_VERB_SET_CHANNEL_STREAMID:
576         st = a->st + node->stindex;
577         if (st->node == NULL) {
578             goto fail;
579         }
580         hda_audio_set_running(st, false);
581         st->stream = (payload >> 4) & 0x0f;
582         st->channel = payload & 0x0f;
583         dprint(a, 2, "%s: stream %d, channel %d\n",
584                st->node->name, st->stream, st->channel);
585         hda_audio_set_running(st, a->running_real[st->output * 16 + st->stream]);
586         hda_codec_response(hda, true, 0);
587         break;
588     case AC_VERB_GET_CONV:
589         st = a->st + node->stindex;
590         if (st->node == NULL) {
591             goto fail;
592         }
593         response = st->stream << 4 | st->channel;
594         hda_codec_response(hda, true, response);
595         break;
596     case AC_VERB_SET_STREAM_FORMAT:
597         st = a->st + node->stindex;
598         if (st->node == NULL) {
599             goto fail;
600         }
601         st->format = payload;
602         hda_codec_parse_fmt(st->format, &st->as);
603         hda_audio_setup(st);
604         hda_codec_response(hda, true, 0);
605         break;
606     case AC_VERB_GET_STREAM_FORMAT:
607         st = a->st + node->stindex;
608         if (st->node == NULL) {
609             goto fail;
610         }
611         hda_codec_response(hda, true, st->format);
612         break;
613     case AC_VERB_GET_AMP_GAIN_MUTE:
614         st = a->st + node->stindex;
615         if (st->node == NULL) {
616             goto fail;
617         }
618         if (payload & AC_AMP_GET_LEFT) {
619             response = st->gain_left | (st->mute_left ? AC_AMP_MUTE : 0);
620         } else {
621             response = st->gain_right | (st->mute_right ? AC_AMP_MUTE : 0);
622         }
623         hda_codec_response(hda, true, response);
624         break;
625     case AC_VERB_SET_AMP_GAIN_MUTE:
626         st = a->st + node->stindex;
627         if (st->node == NULL) {
628             goto fail;
629         }
630         dprint(a, 1, "amp (%s): %s%s%s%s index %d  gain %3d %s\n",
631                st->node->name,
632                (payload & AC_AMP_SET_OUTPUT) ? "o" : "-",
633                (payload & AC_AMP_SET_INPUT)  ? "i" : "-",
634                (payload & AC_AMP_SET_LEFT)   ? "l" : "-",
635                (payload & AC_AMP_SET_RIGHT)  ? "r" : "-",
636                (payload & AC_AMP_SET_INDEX) >> AC_AMP_SET_INDEX_SHIFT,
637                (payload & AC_AMP_GAIN),
638                (payload & AC_AMP_MUTE) ? "muted" : "");
639         if (payload & AC_AMP_SET_LEFT) {
640             st->gain_left = payload & AC_AMP_GAIN;
641             st->mute_left = payload & AC_AMP_MUTE;
642         }
643         if (payload & AC_AMP_SET_RIGHT) {
644             st->gain_right = payload & AC_AMP_GAIN;
645             st->mute_right = payload & AC_AMP_MUTE;
646         }
647         hda_audio_set_amp(st);
648         hda_codec_response(hda, true, 0);
649         break;
650 
651     /* not supported */
652     case AC_VERB_SET_POWER_STATE:
653     case AC_VERB_GET_POWER_STATE:
654     case AC_VERB_GET_SDI_SELECT:
655         hda_codec_response(hda, true, 0);
656         break;
657     default:
658         goto fail;
659     }
660     return;
661 
662 fail:
663     dprint(a, 1, "%s: not handled: nid %d (%s), verb 0x%x, payload 0x%x\n",
664            __func__, nid, node ? node->name : "?", verb, payload);
665     hda_codec_response(hda, true, 0);
666 }
667 
hda_audio_stream(HDACodecDevice * hda,uint32_t stnr,bool running,bool output)668 static void hda_audio_stream(HDACodecDevice *hda, uint32_t stnr, bool running, bool output)
669 {
670     HDAAudioState *a = HDA_AUDIO(hda);
671     int s;
672 
673     a->running_compat[stnr] = running;
674     a->running_real[output * 16 + stnr] = running;
675     for (s = 0; s < ARRAY_SIZE(a->st); s++) {
676         if (a->st[s].node == NULL) {
677             continue;
678         }
679         if (a->st[s].output != output) {
680             continue;
681         }
682         if (a->st[s].stream != stnr) {
683             continue;
684         }
685         hda_audio_set_running(&a->st[s], running);
686     }
687 }
688 
hda_audio_init(HDACodecDevice * hda,const struct desc_codec * desc,Error ** errp)689 static void hda_audio_init(HDACodecDevice *hda,
690                            const struct desc_codec *desc,
691                            Error **errp)
692 {
693     HDAAudioState *a = HDA_AUDIO(hda);
694     HDAAudioStream *st;
695     const desc_node *node;
696     const desc_param *param;
697     uint32_t i, type;
698 
699     if (!AUD_register_card("hda", &a->card, errp)) {
700         return;
701     }
702 
703     a->desc = desc;
704     a->name = object_get_typename(OBJECT(a));
705     dprint(a, 1, "%s: cad %d\n", __func__, a->hda.cad);
706 
707     for (i = 0; i < a->desc->nnodes; i++) {
708         node = a->desc->nodes + i;
709         param = hda_codec_find_param(node, AC_PAR_AUDIO_WIDGET_CAP);
710         if (param == NULL) {
711             continue;
712         }
713         type = (param->val & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
714         switch (type) {
715         case AC_WID_AUD_OUT:
716         case AC_WID_AUD_IN:
717             assert(node->stindex < ARRAY_SIZE(a->st));
718             st = a->st + node->stindex;
719             st->state = a;
720             st->node = node;
721             if (type == AC_WID_AUD_OUT) {
722                 /* unmute output by default */
723                 st->gain_left = QEMU_HDA_AMP_STEPS;
724                 st->gain_right = QEMU_HDA_AMP_STEPS;
725                 st->compat_bpos = sizeof(st->compat_buf);
726                 st->output = true;
727                 st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL,
728                                         hda_audio_output_timer, st);
729             } else {
730                 st->output = false;
731                 st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL,
732                                         hda_audio_input_timer, st);
733             }
734             st->format = AC_FMT_TYPE_PCM | AC_FMT_BITS_16 |
735                 (1 << AC_FMT_CHAN_SHIFT);
736             hda_codec_parse_fmt(st->format, &st->as);
737             hda_audio_setup(st);
738             break;
739         }
740     }
741 }
742 
hda_audio_exit(HDACodecDevice * hda)743 static void hda_audio_exit(HDACodecDevice *hda)
744 {
745     HDAAudioState *a = HDA_AUDIO(hda);
746     HDAAudioStream *st;
747     int i;
748 
749     dprint(a, 1, "%s\n", __func__);
750     for (i = 0; i < ARRAY_SIZE(a->st); i++) {
751         st = a->st + i;
752         if (st->node == NULL) {
753             continue;
754         }
755         timer_free(st->buft);
756         if (st->output) {
757             AUD_close_out(&a->card, st->voice.out);
758         } else {
759             AUD_close_in(&a->card, st->voice.in);
760         }
761     }
762     AUD_remove_card(&a->card);
763 }
764 
hda_audio_post_load(void * opaque,int version)765 static int hda_audio_post_load(void *opaque, int version)
766 {
767     HDAAudioState *a = opaque;
768     HDAAudioStream *st;
769     int i;
770 
771     dprint(a, 1, "%s\n", __func__);
772     if (version == 1) {
773         /* assume running_compat[] is for output streams */
774         for (i = 0; i < ARRAY_SIZE(a->running_compat); i++)
775             a->running_real[16 + i] = a->running_compat[i];
776     }
777 
778     for (i = 0; i < ARRAY_SIZE(a->st); i++) {
779         st = a->st + i;
780         if (st->node == NULL)
781             continue;
782         hda_codec_parse_fmt(st->format, &st->as);
783         hda_audio_setup(st);
784         hda_audio_set_amp(st);
785         hda_audio_set_running(st, a->running_real[st->output * 16 + st->stream]);
786     }
787     return 0;
788 }
789 
hda_audio_reset(DeviceState * dev)790 static void hda_audio_reset(DeviceState *dev)
791 {
792     HDAAudioState *a = HDA_AUDIO(dev);
793     HDAAudioStream *st;
794     int i;
795 
796     dprint(a, 1, "%s\n", __func__);
797     for (i = 0; i < ARRAY_SIZE(a->st); i++) {
798         st = a->st + i;
799         if (st->node != NULL) {
800             hda_audio_set_running(st, false);
801         }
802     }
803 }
804 
vmstate_hda_audio_stream_buf_needed(void * opaque)805 static bool vmstate_hda_audio_stream_buf_needed(void *opaque)
806 {
807     HDAAudioStream *st = opaque;
808     return st->state && st->state->use_timer;
809 }
810 
811 static const VMStateDescription vmstate_hda_audio_stream_buf = {
812     .name = "hda-audio-stream/buffer",
813     .version_id = 1,
814     .needed = vmstate_hda_audio_stream_buf_needed,
815     .fields = (const VMStateField[]) {
816         VMSTATE_BUFFER(buf, HDAAudioStream),
817         VMSTATE_INT64(rpos, HDAAudioStream),
818         VMSTATE_INT64(wpos, HDAAudioStream),
819         VMSTATE_TIMER_PTR(buft, HDAAudioStream),
820         VMSTATE_INT64(buft_start, HDAAudioStream),
821         VMSTATE_END_OF_LIST()
822     }
823 };
824 
825 static const VMStateDescription vmstate_hda_audio_stream = {
826     .name = "hda-audio-stream",
827     .version_id = 1,
828     .fields = (const VMStateField[]) {
829         VMSTATE_UINT32(stream, HDAAudioStream),
830         VMSTATE_UINT32(channel, HDAAudioStream),
831         VMSTATE_UINT32(format, HDAAudioStream),
832         VMSTATE_UINT32(gain_left, HDAAudioStream),
833         VMSTATE_UINT32(gain_right, HDAAudioStream),
834         VMSTATE_BOOL(mute_left, HDAAudioStream),
835         VMSTATE_BOOL(mute_right, HDAAudioStream),
836         VMSTATE_UINT32(compat_bpos, HDAAudioStream),
837         VMSTATE_BUFFER(compat_buf, HDAAudioStream),
838         VMSTATE_END_OF_LIST()
839     },
840     .subsections = (const VMStateDescription * const []) {
841         &vmstate_hda_audio_stream_buf,
842         NULL
843     }
844 };
845 
846 static const VMStateDescription vmstate_hda_audio = {
847     .name = "hda-audio",
848     .version_id = 2,
849     .post_load = hda_audio_post_load,
850     .fields = (const VMStateField[]) {
851         VMSTATE_STRUCT_ARRAY(st, HDAAudioState, 4, 0,
852                              vmstate_hda_audio_stream,
853                              HDAAudioStream),
854         VMSTATE_BOOL_ARRAY(running_compat, HDAAudioState, 16),
855         VMSTATE_BOOL_ARRAY_V(running_real, HDAAudioState, 2 * 16, 2),
856         VMSTATE_END_OF_LIST()
857     }
858 };
859 
860 static Property hda_audio_properties[] = {
861     DEFINE_AUDIO_PROPERTIES(HDAAudioState, card),
862     DEFINE_PROP_UINT32("debug", HDAAudioState, debug,   0),
863     DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer,  true),
864     DEFINE_PROP_BOOL("use-timer", HDAAudioState, use_timer,  true),
865     DEFINE_PROP_END_OF_LIST(),
866 };
867 
hda_audio_init_output(HDACodecDevice * hda,Error ** errp)868 static void hda_audio_init_output(HDACodecDevice *hda, Error **errp)
869 {
870     HDAAudioState *a = HDA_AUDIO(hda);
871     const struct desc_codec *desc = &output_mixemu;
872 
873     if (!a->mixer) {
874         desc = &output_nomixemu;
875     }
876 
877     hda_audio_init(hda, desc, errp);
878 }
879 
hda_audio_init_duplex(HDACodecDevice * hda,Error ** errp)880 static void hda_audio_init_duplex(HDACodecDevice *hda, Error **errp)
881 {
882     HDAAudioState *a = HDA_AUDIO(hda);
883     const struct desc_codec *desc = &duplex_mixemu;
884 
885     if (!a->mixer) {
886         desc = &duplex_nomixemu;
887     }
888 
889     hda_audio_init(hda, desc, errp);
890 }
891 
hda_audio_init_micro(HDACodecDevice * hda,Error ** errp)892 static void hda_audio_init_micro(HDACodecDevice *hda, Error **errp)
893 {
894     HDAAudioState *a = HDA_AUDIO(hda);
895     const struct desc_codec *desc = &micro_mixemu;
896 
897     if (!a->mixer) {
898         desc = &micro_nomixemu;
899     }
900 
901     hda_audio_init(hda, desc, errp);
902 }
903 
hda_audio_base_class_init(ObjectClass * klass,void * data)904 static void hda_audio_base_class_init(ObjectClass *klass, void *data)
905 {
906     DeviceClass *dc = DEVICE_CLASS(klass);
907     HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
908 
909     k->exit = hda_audio_exit;
910     k->command = hda_audio_command;
911     k->stream = hda_audio_stream;
912     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
913     dc->reset = hda_audio_reset;
914     dc->vmsd = &vmstate_hda_audio;
915     device_class_set_props(dc, hda_audio_properties);
916 }
917 
918 static const TypeInfo hda_audio_info = {
919     .name          = TYPE_HDA_AUDIO,
920     .parent        = TYPE_HDA_CODEC_DEVICE,
921     .instance_size = sizeof(HDAAudioState),
922     .class_init    = hda_audio_base_class_init,
923     .abstract      = true,
924 };
925 
hda_audio_output_class_init(ObjectClass * klass,void * data)926 static void hda_audio_output_class_init(ObjectClass *klass, void *data)
927 {
928     DeviceClass *dc = DEVICE_CLASS(klass);
929     HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
930 
931     k->init = hda_audio_init_output;
932     dc->desc = "HDA Audio Codec, output-only (line-out)";
933 }
934 
935 static const TypeInfo hda_audio_output_info = {
936     .name          = "hda-output",
937     .parent        = TYPE_HDA_AUDIO,
938     .class_init    = hda_audio_output_class_init,
939 };
940 
hda_audio_duplex_class_init(ObjectClass * klass,void * data)941 static void hda_audio_duplex_class_init(ObjectClass *klass, void *data)
942 {
943     DeviceClass *dc = DEVICE_CLASS(klass);
944     HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
945 
946     k->init = hda_audio_init_duplex;
947     dc->desc = "HDA Audio Codec, duplex (line-out, line-in)";
948 }
949 
950 static const TypeInfo hda_audio_duplex_info = {
951     .name          = "hda-duplex",
952     .parent        = TYPE_HDA_AUDIO,
953     .class_init    = hda_audio_duplex_class_init,
954 };
955 
hda_audio_micro_class_init(ObjectClass * klass,void * data)956 static void hda_audio_micro_class_init(ObjectClass *klass, void *data)
957 {
958     DeviceClass *dc = DEVICE_CLASS(klass);
959     HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
960 
961     k->init = hda_audio_init_micro;
962     dc->desc = "HDA Audio Codec, duplex (speaker, microphone)";
963 }
964 
965 static const TypeInfo hda_audio_micro_info = {
966     .name          = "hda-micro",
967     .parent        = TYPE_HDA_AUDIO,
968     .class_init    = hda_audio_micro_class_init,
969 };
970 
hda_audio_register_types(void)971 static void hda_audio_register_types(void)
972 {
973     type_register_static(&hda_audio_info);
974     type_register_static(&hda_audio_output_info);
975     type_register_static(&hda_audio_duplex_info);
976     type_register_static(&hda_audio_micro_info);
977 }
978 
979 type_init(hda_audio_register_types)
980