aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/hda_codec.c1
-rw-r--r--sound/pci/hda/hda_patch.h3
-rw-r--r--sound/pci/hda/patch_sigmatel.c560
4 files changed, 565 insertions, 1 deletions
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 570a59d33b41..bd8cb33c4fb4 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,5 +1,5 @@
1snd-hda-intel-objs := hda_intel.o 1snd-hda-intel-objs := hda_intel.o
2snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o 2snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o
3ifdef CONFIG_PROC_FS 3ifdef CONFIG_PROC_FS
4snd-hda-codec-objs += hda_proc.o 4snd-hda-codec-objs += hda_proc.o
5endif 5endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 9ed117ac0c09..be6cba349394 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -51,6 +51,7 @@ static struct hda_vendor_id hda_vendor_ids[] = {
51 { 0x10ec, "Realtek" }, 51 { 0x10ec, "Realtek" },
52 { 0x13f6, "C-Media" }, 52 { 0x13f6, "C-Media" },
53 { 0x434d, "C-Media" }, 53 { 0x434d, "C-Media" },
54 { 0x8384, "SigmaTel" },
54 {} /* terminator */ 55 {} /* terminator */
55}; 56};
56 57
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
index cf6abce42bc9..a5de684b6944 100644
--- a/sound/pci/hda/hda_patch.h
+++ b/sound/pci/hda/hda_patch.h
@@ -8,10 +8,13 @@ extern struct hda_codec_preset snd_hda_preset_realtek[];
8extern struct hda_codec_preset snd_hda_preset_cmedia[]; 8extern struct hda_codec_preset snd_hda_preset_cmedia[];
9/* Analog Devices codecs */ 9/* Analog Devices codecs */
10extern struct hda_codec_preset snd_hda_preset_analog[]; 10extern struct hda_codec_preset snd_hda_preset_analog[];
11/* SigmaTel codecs */
12extern struct hda_codec_preset snd_hda_preset_sigmatel[];
11 13
12static const struct hda_codec_preset *hda_preset_tables[] = { 14static const struct hda_codec_preset *hda_preset_tables[] = {
13 snd_hda_preset_realtek, 15 snd_hda_preset_realtek,
14 snd_hda_preset_cmedia, 16 snd_hda_preset_cmedia,
15 snd_hda_preset_analog, 17 snd_hda_preset_analog,
18 snd_hda_preset_sigmatel,
16 NULL 19 NULL
17}; 20};
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
new file mode 100644
index 000000000000..1534e20af63d
--- /dev/null
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -0,0 +1,560 @@
1/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * HD audio interface patch for SigmaTel STAC92xx
5 *
6 * Copyright (c) 2005 Embedded Alley Solutions, Inc.
7 * <matt@embeddedalley.com>
8 *
9 * Based on patch_cmedia.c and patch_realtek.c
10 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
11 *
12 * This driver is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This driver is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#include <sound/driver.h>
28#include <linux/init.h>
29#include <linux/delay.h>
30#include <linux/slab.h>
31#include <linux/pci.h>
32#include <sound/core.h>
33#include "hda_codec.h"
34#include "hda_local.h"
35
36#undef STAC_TEST
37
38struct sigmatel_spec {
39 /* playback */
40 struct hda_multi_out multiout;
41 hda_nid_t playback_nid;
42
43 /* capture */
44 hda_nid_t *adc_nids;
45 hda_nid_t *mux_nids;
46 unsigned int num_adcs;
47 hda_nid_t capture_nid;
48
49 /* power management*/
50 hda_nid_t *pstate_nids;
51 unsigned int num_pstates;
52
53 /* pin widgets */
54 hda_nid_t *pin_nids;
55 unsigned int num_pins;
56#ifdef STAC_TEST
57 unsigned int *pin_configs;
58#endif
59
60 /* codec specific stuff */
61 struct hda_verb *init;
62 snd_kcontrol_new_t *mixer;
63
64 /* capture source */
65 const struct hda_input_mux *input_mux;
66 unsigned int cur_mux[2];
67
68 /* channel mode */
69 unsigned int num_ch_modes;
70 unsigned int cur_ch_mode;
71 const struct sigmatel_channel_mode *channel_modes;
72
73 struct hda_pcm pcm_rec[1]; /* PCM information */
74};
75
76static hda_nid_t stac9200_adc_nids[1] = {
77 0x03,
78};
79
80static hda_nid_t stac9200_mux_nids[1] = {
81 0x0c,
82};
83
84static hda_nid_t stac9200_dac_nids[1] = {
85 0x02,
86};
87
88static hda_nid_t stac9200_pstate_nids[3] = {
89 0x01, 0x02, 0x03,
90};
91
92static hda_nid_t stac9200_pin_nids[8] = {
93 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
94};
95
96static hda_nid_t stac922x_adc_nids[2] = {
97 0x06, 0x07,
98};
99
100static hda_nid_t stac922x_mux_nids[2] = {
101 0x12, 0x13,
102};
103
104static hda_nid_t stac922x_dac_nids[4] = {
105 0x02, 0x03, 0x04, 0x05,
106};
107
108static hda_nid_t stac922x_pstate_nids[7] = {
109 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
110};
111
112static hda_nid_t stac922x_pin_nids[10] = {
113 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
114 0x0f, 0x10, 0x11, 0x15, 0x1b,
115};
116
117static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
118{
119 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
120 struct sigmatel_spec *spec = codec->spec;
121 return snd_hda_input_mux_info(spec->input_mux, uinfo);
122}
123
124static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
125{
126 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
127 struct sigmatel_spec *spec = codec->spec;
128 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
129
130 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
131 return 0;
132}
133
134static int stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
135{
136 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
137 struct sigmatel_spec *spec = codec->spec;
138 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
139
140 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
141 spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);
142}
143
144static struct hda_verb stac9200_ch2_init[] = {
145 /* set dac0mux for dac converter */
146 { 0x07, 0x701, 0x00},
147 {}
148};
149
150static struct hda_verb stac922x_ch2_init[] = {
151 /* set master volume and direct control */
152 { 0x16, 0x70f, 0xff},
153 {}
154};
155
156struct sigmatel_channel_mode {
157 unsigned int channels;
158 const struct hda_verb *sequence;
159};
160
161static snd_kcontrol_new_t stac9200_mixer[] = {
162 HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
163 HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
164 {
165 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
166 .name = "Input Source",
167 .count = 1,
168 .info = stac92xx_mux_enum_info,
169 .get = stac92xx_mux_enum_get,
170 .put = stac92xx_mux_enum_put,
171 },
172 HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
173 HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
174 HDA_CODEC_VOLUME("Input Mux Volume", 0x0c, 0, HDA_OUTPUT),
175 { } /* end */
176};
177
178static snd_kcontrol_new_t stac922x_mixer[] = {
179 HDA_CODEC_VOLUME("PCM Playback Volume", 0x2, 0x0, HDA_OUTPUT),
180 HDA_CODEC_MUTE("PCM Playback Switch", 0x2, 0x0, HDA_OUTPUT),
181 {
182 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
183 .name = "Input Source",
184 .count = 1,
185 .info = stac92xx_mux_enum_info,
186 .get = stac92xx_mux_enum_get,
187 .put = stac92xx_mux_enum_put,
188 },
189 HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT),
190 HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT),
191 HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT),
192 { } /* end */
193};
194
195static struct hda_input_mux stac9200_input_mux = {
196 .num_items = 5,
197 .items = {
198 { "Port B", 0x0 },
199 { "Port C", 0x1 },
200 { "Port D", 0x2 },
201 { "Port A", 0x3 },
202 { "CD", 0x4 },
203 }
204};
205
206static struct hda_input_mux stac922x_input_mux = {
207 .num_items = 7,
208 .items = {
209 { "Port E", 0x0 },
210 { "CD", 0x1 },
211 { "Port F", 0x2 },
212 { "Port B", 0x3 },
213 { "Port C", 0x4 },
214 { "Port D", 0x5 },
215 { "Port A", 0x6 },
216 }
217};
218
219static int stac92xx_build_controls(struct hda_codec *codec)
220{
221 struct sigmatel_spec *spec = codec->spec;
222 int err;
223
224 err = snd_hda_add_new_ctls(codec, spec->mixer);
225 if (err < 0)
226 return err;
227
228 return 0;
229}
230
231#ifdef STAC_TEST
232static unsigned int stac9200_pin_configs[8] = {
233 0x40000100, 0x40000100, 0x0221401f, 0x01114010,
234 0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
235};
236
237static unsigned int stac922x_pin_configs[14] = {
238 0x40000100, 0x40000100, 0x40000100, 0x01114010,
239 0x01813122, 0x40000100, 0x40000100, 0x40000100,
240 0x40000100, 0x40000100,
241};
242
243static void stac92xx_set_config_regs(struct hda_codec *codec)
244{
245 int i;
246 struct sigmatel_spec *spec = codec->spec;
247 unsigned int pin_cfg;
248
249 for (i=0; i < spec->num_pins; i++) {
250 snd_hda_codec_write(codec, spec->pin_nids[i], 0,
251 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
252 spec->pin_configs[i] & 0x000000ff);
253 snd_hda_codec_write(codec, spec->pin_nids[i], 0,
254 AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
255 (spec->pin_configs[i] & 0x0000ff00) >> 8);
256 snd_hda_codec_write(codec, spec->pin_nids[i], 0,
257 AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
258 (spec->pin_configs[i] & 0x00ff0000) >> 16);
259 snd_hda_codec_write(codec, spec->pin_nids[i], 0,
260 AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
261 spec->pin_configs[i] >> 24);
262 pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
263 AC_VERB_GET_CONFIG_DEFAULT,
264 0x00);
265 printk("pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg);
266 }
267}
268#endif
269
270static int stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int value)
271{
272 unsigned int pin_ctl;
273
274 pin_ctl = snd_hda_codec_read(codec, nid, 0,
275 AC_VERB_GET_PIN_WIDGET_CONTROL,
276 0x00);
277 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
278 pin_ctl | value);
279
280 return 0;
281}
282
283static int stac92xx_set_vref(struct hda_codec *codec, hda_nid_t nid)
284{
285 unsigned int vref_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) >> AC_PINCAP_VREF_SHIFT;
286 unsigned int vref_ctl = AC_PINCTL_VREF_HIZ;
287
288 if (vref_caps & AC_PINCAP_VREF_100)
289 vref_ctl = AC_PINCTL_VREF_100;
290 else if (vref_caps & AC_PINCAP_VREF_80)
291 vref_ctl = AC_PINCTL_VREF_80;
292 else if (vref_caps & AC_PINCAP_VREF_50)
293 vref_ctl = AC_PINCTL_VREF_50;
294 else if (vref_caps & AC_PINCAP_VREF_GRD)
295 vref_ctl = AC_PINCTL_VREF_GRD;
296
297 stac92xx_set_pinctl(codec, nid, vref_ctl);
298
299 return 0;
300}
301
302static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg)
303{
304 switch((pin_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) {
305 case AC_JACK_HP_OUT:
306 /* Enable HP amp */
307 stac92xx_set_pinctl(codec, nid, AC_PINCTL_HP_EN);
308 /* Fall through */
309 case AC_JACK_LINE_OUT:
310 case AC_JACK_SPEAKER:
311 /* Enable output */
312 stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
313 break;
314 case AC_JACK_MIC_IN:
315 /* Set vref */
316 stac92xx_set_vref(codec, nid);
317 case AC_JACK_CD:
318 case AC_JACK_LINE_IN:
319 case AC_JACK_AUX:
320 /* Enable input */
321 stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
322 break;
323 }
324
325 return 0;
326}
327
328static int stac92xx_config_pins(struct hda_codec *codec)
329{
330 struct sigmatel_spec *spec = codec->spec;
331 int i;
332 unsigned int pin_cfg;
333
334 for (i=0; i < spec->num_pins; i++) {
335 /* Default to disabled */
336 snd_hda_codec_write(codec, spec->pin_nids[i], 0,
337 AC_VERB_SET_PIN_WIDGET_CONTROL,
338 0x00);
339
340 pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
341 AC_VERB_GET_CONFIG_DEFAULT,
342 0x00);
343 if (((pin_cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) == AC_JACK_PORT_NONE)
344 continue; /* Move on */
345
346 stac92xx_config_pin(codec, spec->pin_nids[i], pin_cfg);
347 }
348
349 return 0;
350}
351
352static int stac92xx_init(struct hda_codec *codec)
353{
354 struct sigmatel_spec *spec = codec->spec;
355 int i;
356
357 for (i=0; i < spec->num_pstates; i++)
358 snd_hda_codec_write(codec, spec->pstate_nids[i], 0,
359 AC_VERB_SET_POWER_STATE, 0x00);
360
361 mdelay(100);
362
363 snd_hda_sequence_write(codec, spec->init);
364
365#ifdef STAC_TEST
366 stac92xx_set_config_regs(codec);
367#endif
368
369 stac92xx_config_pins(codec);
370
371 return 0;
372}
373
374/*
375 * Analog playback callbacks
376 */
377static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
378 struct hda_codec *codec,
379 snd_pcm_substream_t *substream)
380{
381 struct sigmatel_spec *spec = codec->spec;
382 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
383}
384
385static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
386 struct hda_codec *codec,
387 unsigned int stream_tag,
388 unsigned int format,
389 snd_pcm_substream_t *substream)
390{
391 struct sigmatel_spec *spec = codec->spec;
392 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
393 format, substream);
394}
395
396static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
397 struct hda_codec *codec,
398 snd_pcm_substream_t *substream)
399{
400 struct sigmatel_spec *spec = codec->spec;
401 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
402}
403
404/*
405 * Analog capture callbacks
406 */
407static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
408 struct hda_codec *codec,
409 unsigned int stream_tag,
410 unsigned int format,
411 snd_pcm_substream_t *substream)
412{
413 struct sigmatel_spec *spec = codec->spec;
414
415 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
416 stream_tag, 0, format);
417 return 0;
418}
419
420static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
421 struct hda_codec *codec,
422 snd_pcm_substream_t *substream)
423{
424 struct sigmatel_spec *spec = codec->spec;
425
426 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
427 return 0;
428}
429
430static struct hda_pcm_stream stac92xx_pcm_analog_playback = {
431 .substreams = 1,
432 .channels_min = 2,
433 .channels_max = 2,
434 .nid = 0x02, /* NID to query formats and rates */
435 .ops = {
436 .open = stac92xx_playback_pcm_open,
437 .prepare = stac92xx_playback_pcm_prepare,
438 .cleanup = stac92xx_playback_pcm_cleanup
439 },
440};
441
442static struct hda_pcm_stream stac92xx_pcm_analog_capture = {
443 .substreams = 2,
444 .channels_min = 2,
445 .channels_max = 2,
446 .nid = 0x06, /* NID to query formats and rates */
447 .ops = {
448 .prepare = stac92xx_capture_pcm_prepare,
449 .cleanup = stac92xx_capture_pcm_cleanup
450 },
451};
452
453static int stac92xx_build_pcms(struct hda_codec *codec)
454{
455 struct sigmatel_spec *spec = codec->spec;
456 struct hda_pcm *info = spec->pcm_rec;
457
458 codec->num_pcms = 1;
459 codec->pcm_info = info;
460
461 info->name = "STAC92xx";
462 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback;
463 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->playback_nid;
464 info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;
465 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->capture_nid;
466
467 return 0;
468}
469
470static void stac92xx_free(struct hda_codec *codec)
471{
472 kfree(codec->spec);
473}
474
475static struct hda_codec_ops stac92xx_patch_ops = {
476 .build_controls = stac92xx_build_controls,
477 .build_pcms = stac92xx_build_pcms,
478 .init = stac92xx_init,
479 .free = stac92xx_free,
480};
481
482static int patch_stac9200(struct hda_codec *codec)
483{
484 struct sigmatel_spec *spec;
485
486 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
487 if (spec == NULL)
488 return -ENOMEM;
489
490 codec->spec = spec;
491
492 spec->multiout.max_channels = 2;
493 spec->multiout.num_dacs = 1;
494 spec->multiout.dac_nids = stac9200_dac_nids;
495 spec->adc_nids = stac9200_adc_nids;
496 spec->mux_nids = stac9200_mux_nids;
497 spec->input_mux = &stac9200_input_mux;
498 spec->pstate_nids = stac9200_pstate_nids;
499 spec->num_pstates = 3;
500 spec->pin_nids = stac9200_pin_nids;
501#ifdef STAC_TEST
502 spec->pin_configs = stac9200_pin_configs;
503#endif
504 spec->num_pins = 8;
505 spec->init = stac9200_ch2_init;
506 spec->mixer = stac9200_mixer;
507 spec->playback_nid = 0x02;
508 spec->capture_nid = 0x03;
509
510 codec->patch_ops = stac92xx_patch_ops;
511
512 return 0;
513}
514
515static int patch_stac922x(struct hda_codec *codec)
516{
517 struct sigmatel_spec *spec;
518
519 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
520 if (spec == NULL)
521 return -ENOMEM;
522
523 codec->spec = spec;
524
525 spec->multiout.max_channels = 2;
526 spec->multiout.num_dacs = 4;
527 spec->multiout.dac_nids = stac922x_dac_nids;
528 spec->adc_nids = stac922x_adc_nids;
529 spec->mux_nids = stac922x_mux_nids;
530 spec->input_mux = &stac922x_input_mux;
531 spec->pstate_nids = stac922x_pstate_nids;
532 spec->num_pstates = 7;
533 spec->pin_nids = stac922x_pin_nids;
534#ifdef STAC_TEST
535 spec->pin_configs = stac922x_pin_configs;
536#endif
537 spec->num_pins = 10;
538 spec->init = stac922x_ch2_init;
539 spec->mixer = stac922x_mixer;
540 spec->playback_nid = 0x02;
541 spec->capture_nid = 0x06;
542
543 codec->patch_ops = stac92xx_patch_ops;
544
545 return 0;
546}
547
548/*
549 * patch entries
550 */
551struct hda_codec_preset snd_hda_preset_sigmatel[] = {
552 { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },
553 { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },
554 { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },
555 { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x },
556 { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x },
557 { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x },
558 { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x },
559 {} /* terminator */
560};