~ubuntu-branches/ubuntu/oneiric/oss4/oneiric-proposed

« back to all changes in this revision

Viewing changes to utils/mixgen2.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefano Rivera
  • Date: 2011-06-16 20:37:48 UTC
  • mfrom: (5.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110616203748-jbrxik6ql33z54co
Tags: 4.2-build2004-1ubuntu1
* Merge from Debian unstable.
  - Supports our current kernel (LP: #746048)
  Remaining changes:
  - debian/oss4-dkms.dkms.in: s/source/build/ in Kernel headers paths.
* ld-as-needed.patch: Re-order CC arguments to enable building with ld
  --as-needed (LP: #770972)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Temporary utility used to develop the next hdaudio driver
 
3
 * version. Not usable.
 
4
 */
 
5
/*
 
6
 *
 
7
 * This file is part of Open Sound System.
 
8
 *
 
9
 * Copyright (C) 4Front Technologies 1996-2008.
 
10
 *
 
11
 * This this source file is released under GPL v2 license (no other versions).
 
12
 * See the COPYING file included in the main directory of this source
 
13
 * distribution for the license terms and conditions.
 
14
 *
 
15
 */
 
16
 
 
17
#include <stdio.h>
 
18
#include <stdlib.h>
 
19
#include <unistd.h>
 
20
#include <fcntl.h>
 
21
#include <sys/ioctl.h>
 
22
#include <errno.h>
 
23
#include <string.h>
 
24
#include <soundcard.h>
 
25
#include <stdarg.h>
 
26
 
 
27
#define DRIVER_NICK "hdaudio"
 
28
#define CE_CONT 0
 
29
#define CE_NOTE 1
 
30
#define CE_WARN 2
 
31
 
 
32
#define DDB(x)
 
33
 
 
34
#define PMALLOC(osdev, s)       malloc(s)
 
35
 
 
36
typedef int sound_os_info, mixer_create_controls_t;
 
37
 
 
38
typedef struct
 
39
{
 
40
  char *hw_info;
 
41
} oss_device_t;
 
42
 
 
43
#include <hdaudio.h>
 
44
 
 
45
#define ioctl_arg int
 
46
#define mixer_ext_init_fn int
 
47
#include <hdaudio_codec.h>
 
48
//#include <hdaudio_codecids.h>
 
49
 
 
50
int fd;
 
51
 
 
52
#undef corb_read
 
53
#undef corb_write
 
54
 
 
55
typedef struct
 
56
{
 
57
        int association, sequence;
 
58
        int nwidgets;
 
59
        int jack_count;
 
60
 
 
61
#define PATH_MAXWID     8
 
62
        widget_t *widgets[PATH_MAXWID];
 
63
} path_t;
 
64
 
 
65
#define MAX_PATHS       32
 
66
path_t *paths[MAX_PATHS];
 
67
int npaths=0;
 
68
 
 
69
int
 
70
corb_write (void *dc, unsigned int cad, unsigned int nid, unsigned int d,
 
71
            unsigned int verb, unsigned int parm)
 
72
{
 
73
  unsigned int tmp;
 
74
 
 
75
  tmp = (cad << 28) | (d << 27) | (nid << 20) | (verb << 8) | parm;
 
76
 
 
77
  if (ioctl (fd, HDA_IOCTL_WRITE, &tmp) == -1)
 
78
    {
 
79
      perror ("HDA_IOCTL_WRITE");
 
80
      return 0;
 
81
    }
 
82
 
 
83
  return 1;
 
84
}
 
85
 
 
86
static int
 
87
corb_read (void *dc, unsigned int cad, unsigned int nid, unsigned int d,
 
88
           unsigned int verb, unsigned int parm, unsigned int *upper,
 
89
           unsigned int *lower)
 
90
{
 
91
  unsigned int tmp;
 
92
 
 
93
  tmp = (cad << 28) | (d << 27) | (nid << 20) | (verb << 8) | parm;
 
94
 
 
95
  if (ioctl (fd, HDA_IOCTL_READ, &tmp) == -1)
 
96
    {
 
97
      /* perror("HDA_IOCTL_READ"); */
 
98
      if (errno == EINVAL)
 
99
        {
 
100
          fprintf (stderr, "hdaudio_snoopy mode is not available\n");
 
101
          exit (-1);
 
102
        }
 
103
      return 0;
 
104
    }
 
105
 
 
106
  *upper = tmp;
 
107
  *lower = 0;
 
108
 
 
109
  return 1;
 
110
}
 
111
 
 
112
void
 
113
cmn_err (int level, char *s, ...)
 
114
{
 
115
  char tmp[1024], *a[6];
 
116
  va_list ap;
 
117
  int i, n = 0;
 
118
 
 
119
  va_start (ap, s);
 
120
 
 
121
  for (i = 0; i < strlen (s); i++)
 
122
    if (s[i] == '%')
 
123
      n++;
 
124
 
 
125
  for (i = 0; i < n && i < 6; i++)
 
126
    {
 
127
      a[i] = va_arg (ap, char *);
 
128
    }
 
129
 
 
130
  for (i = n; i < 6; i++)
 
131
    a[i] = NULL;
 
132
 
 
133
  if (level == CE_CONT)
 
134
    {
 
135
      sprintf (tmp, s, a[0], a[1], a[2], a[3], a[4], a[5], NULL,
 
136
               NULL, NULL, NULL);
 
137
      printf ("%s", tmp);
 
138
    }
 
139
  else
 
140
    {
 
141
      strcpy (tmp, DRIVER_NICK ": ");
 
142
 
 
143
      sprintf (tmp + strlen (tmp), s, a[0], a[1], a[2], a[3], a[4], a[5],
 
144
               NULL, NULL, NULL, NULL);
 
145
      printf ("%s", tmp);
 
146
    }
 
147
 
 
148
  va_end (ap);
 
149
}
 
150
 
 
151
/*
 
152
 ********************************
 
153
 */
 
154
 
 
155
static const char *widget_id[16] = {
 
156
    "pcm",
 
157
    "rec",
 
158
    "mix",
 
159
    "select",
 
160
    "jack",
 
161
    "power",
 
162
    "vol",
 
163
    "beep",
 
164
    "unkn",
 
165
    "unkn",
 
166
    "unkn",
 
167
    "unkn",
 
168
    "unkn",
 
169
    "unkn",
 
170
    "unkn",
 
171
    "vendor"
 
172
  };
 
173
 
 
174
static int
 
175
attach_pin_widget (hdaudio_mixer_t * mixer, codec_t * codec,
 
176
                   widget_t * widget, int cad, int wid, int group_type)
 
177
{
 
178
  unsigned int conf;
 
179
  int num = codec->jack_number++;
 
180
  unsigned int pincaps, b;
 
181
  int association, sequence;
 
182
  int default_device;
 
183
  int default_loc;
 
184
  int conn;
 
185
 
 
186
  int color;
 
187
  int no_color = 0;
 
188
  char *name = NULL, *loc = "", *color_name = NULL;
 
189
 
 
190
  if (!corb_read (mixer, cad, wid, 0, GET_CONFIG_DEFAULT, 0, &conf, &b))
 
191
    return 0;
 
192
 
 
193
  default_device = (conf >> 20) & 0x0f;
 
194
  default_loc = (conf >> 24) & 0x3f;
 
195
  conn = (conf >> 30) & 0x03;
 
196
 
 
197
  if (!corb_read (mixer, cad, wid, 0,
 
198
                  GET_PARAMETER, HDA_PIN_CAPS, &pincaps, &b))
 
199
    {
 
200
      cmn_err (CE_WARN, "GET_PARAMETER HDA_PIN_CAPS failed\n");
 
201
      return 0;
 
202
    }
 
203
 
 
204
  widget->pincaps = pincaps;
 
205
 
 
206
  if (conf == 0)
 
207
    {
 
208
      cmn_err (CE_WARN,
 
209
               "CONFIG_DEFAULT information not provided by BIOS for cad=%d, wid=%02x\n",
 
210
               cad, wid);
 
211
      cmn_err (CE_CONT, "Cannot work in this system.\n");
 
212
      return 0;
 
213
    }
 
214
 
 
215
  color = (conf >> 12) & 0x0f;
 
216
 
 
217
  association = (conf>>4) & 0xf;
 
218
  sequence = conf & 0xf;
 
219
 
 
220
  if (pincaps & (1 << 6))
 
221
    cmn_err (CE_WARN, "Balanced I/O not supported\n");
 
222
  if (!(pincaps & (1 << 5)))    /* No input */
 
223
    widget->pin_type = PIN_OUT;
 
224
  if (!(pincaps & (1 << 4)))
 
225
    widget->pin_type = PIN_IN;
 
226
 
 
227
  DDB (cmn_err (CE_CONT, "\tConfig default %08x\n", conf));
 
228
 
 
229
  if ((default_loc & 0x0f) == 0x1)      /* Rear panel - default */
 
230
    loc = "";
 
231
  if ((default_loc & 0x0f) == 0x2)      /* Front panel */
 
232
    loc = "fp-";
 
233
  if ((default_loc & 0xf0) == 0x10)     /* Internal func - eg cd/tad/spk */
 
234
    loc = "int-";
 
235
 
 
236
  if (conn == 1)                /* Pin not connected to anything */
 
237
    {
 
238
      widget->skip = 1;
 
239
      widget->skip_output = 1;
 
240
    }
 
241
 
 
242
  widget->association = association;
 
243
  widget->sequence = sequence;
 
244
 
 
245
  switch (default_device)
 
246
    {
 
247
    case 0x0:
 
248
      name = "lineout";
 
249
      widget->pin_type = PIN_OUT;
 
250
      break;
 
251
    case 0x1:
 
252
      name = "speaker";
 
253
      no_color = 1;
 
254
      widget->pin_type = PIN_OUT;
 
255
      break;
 
256
    case 0x2:
 
257
      name = "headphone";
 
258
      widget->pin_type = PIN_OUT;
 
259
      break;
 
260
    case 0x3:
 
261
      name = "cd";
 
262
      no_color = 1;
 
263
      widget->pin_type = PIN_IN;
 
264
      break;
 
265
    case 0x4:
 
266
      name = "spdifout";
 
267
      no_color = 1;
 
268
      widget->pin_type = PIN_OUT;
 
269
      break;
 
270
    case 0x5:
 
271
      name = "digout";
 
272
      no_color = 1;
 
273
      widget->pin_type = PIN_OUT;
 
274
      break;
 
275
    case 0x6:
 
276
      name = "modem";
 
277
      no_color = 1;
 
278
      break;
 
279
    case 0x7:
 
280
      name = "phone";
 
281
      no_color = 1;
 
282
      break;
 
283
    case 0x8:
 
284
      name = "linein";
 
285
      widget->pin_type = PIN_IN;
 
286
      break;
 
287
    case 0x9:
 
288
      name = "aux";
 
289
      break;
 
290
    case 0xa:
 
291
      name = "mic";
 
292
      widget->pin_type = PIN_MIC;
 
293
      break;
 
294
    case 0xb:
 
295
      name = "telephony";
 
296
      no_color = 1;
 
297
      break;
 
298
    case 0xc:
 
299
      name = "spdifin";
 
300
      no_color = 1;
 
301
      break;
 
302
    case 0xd:
 
303
      name = "digin";
 
304
      no_color = 1;
 
305
      break;
 
306
    case 0xe:
 
307
      name = "reserved";
 
308
      no_color = 1;
 
309
      break;
 
310
    case 0xf:                   /* Unused pin widget */
 
311
      widget->skip = 1;
 
312
      widget->skip_output = 1;
 
313
      break;
 
314
    }
 
315
 
 
316
/* process only colored jacks and skip fixed function jacks */
 
317
  switch (color)
 
318
    {
 
319
    case 0x1:
 
320
      color_name = "black";
 
321
      widget->rgbcolor = OSS_RGB_BLACK;
 
322
      break;
 
323
    case 0x2:
 
324
      color_name = "gray";
 
325
      widget->rgbcolor = OSS_RGB_GRAY;
 
326
      break;
 
327
    case 0x3:
 
328
      color_name = "blue";
 
329
      widget->rgbcolor = OSS_RGB_BLUE;
 
330
      break;
 
331
    case 0x4:
 
332
      color_name = "green";
 
333
      widget->rgbcolor = OSS_RGB_GREEN;
 
334
      break;
 
335
    case 0x5:
 
336
      color_name = "red";
 
337
      widget->rgbcolor = OSS_RGB_RED;
 
338
      break;
 
339
    case 0x6:
 
340
      color_name = "orange";
 
341
      widget->rgbcolor = OSS_RGB_ORANGE;
 
342
      break;
 
343
    case 0x7:
 
344
      color_name = "yellow";
 
345
      widget->rgbcolor = OSS_RGB_YELLOW;
 
346
      break;
 
347
    case 0x8:
 
348
      color_name = "purple";
 
349
      widget->rgbcolor = OSS_RGB_PURPLE;
 
350
      break;
 
351
    case 0x9:
 
352
      color_name = "pink";
 
353
      widget->rgbcolor = OSS_RGB_PINK;
 
354
      break;
 
355
    case 0xe:
 
356
      color_name = "white";
 
357
      widget->rgbcolor = OSS_RGB_WHITE;
 
358
      break;
 
359
 
 
360
    default:
 
361
      if (name != NULL)
 
362
        color_name = name;
 
363
      else
 
364
        color_name = "internal";
 
365
    }
 
366
 
 
367
  if (no_color)
 
368
    widget->rgbcolor = 0;
 
369
 
 
370
  if (default_device == 0xf)    /* Not present */
 
371
    {
 
372
      widget->rgbcolor = 0;
 
373
      color_name = "internal";
 
374
    }
 
375
 
 
376
  sprintf (widget->color, "%s%s", loc, color_name);
 
377
 
 
378
  if (name == NULL || default_device == 0x00)
 
379
    name = color_name;
 
380
  sprintf (widget->name, "%s%s", loc, name);
 
381
 
 
382
  DDB(cmn_err(CE_CONT, "\tJack name %s, color %s (%06x)\n", 
 
383
                          widget->name, widget->color, widget->rgbcolor));
 
384
  DDB(cmn_err(CE_CONT, "\tAssociation %x, sequence %x\n", association, sequence));
 
385
 
 
386
printf("Widget %02x: default_device=%d, name=%s, color=%s\n", wid, default_device, widget->name, widget->color);
 
387
  return 1;
 
388
}
 
389
 
 
390
static int
 
391
attach_widget (hdaudio_mixer_t * mixer, int cad, int wid, int group_type)
 
392
{
 
393
  static const char *widget_types[16] = {
 
394
    "Audio output",
 
395
    "Audio input",
 
396
    "Audio mixer",
 
397
    "Audio selector",
 
398
    "Pin complex",
 
399
    "Power widget",
 
400
    "Volume knob",
 
401
    "Beep generator",
 
402
    "Reserved8",
 
403
    "Reserved9",
 
404
    "ReservedA",
 
405
    "ReservedB",
 
406
    "ReservedC",
 
407
    "ReservedD",
 
408
    "ReservedE",
 
409
    "Vendor defined audio"
 
410
  };
 
411
 
 
412
  static const int bit_sizes[] = {
 
413
    8,
 
414
    16,
 
415
    20,
 
416
    24,
 
417
    32
 
418
  };
 
419
 
 
420
  static const unsigned int bit_fmts[] = {
 
421
    AFMT_U8,
 
422
    AFMT_S16_LE,
 
423
    AFMT_S32_LE,
 
424
    AFMT_S32_LE,
 
425
    AFMT_S32_LE
 
426
  };
 
427
 
 
428
  static const int srates[] = {
 
429
    8000,
 
430
    11025,
 
431
    16000,
 
432
    22050,
 
433
    32000,
 
434
    44100,
 
435
    48000,
 
436
    88200,
 
437
    96000,
 
438
    176400,
 
439
    192000,
 
440
    384000
 
441
  };
 
442
 
 
443
  unsigned int widget_caps, b, pstate;
 
444
  unsigned int inamp_caps, outamp_caps;
 
445
  int wid_type;
 
446
  int i;
 
447
 
 
448
  codec_t *codec = mixer->codecs[cad];
 
449
  widget_t *widget;
 
450
 
 
451
  if (codec == NULL)
 
452
    return 0;
 
453
 
 
454
  if (wid >= MAX_WIDGETS)
 
455
    {
 
456
      cmn_err (CE_WARN, "Too many widgets for codec %d (%d/%d)\n", cad, wid,
 
457
               MAX_WIDGETS);
 
458
      return 0;
 
459
    }
 
460
 
 
461
  mixer->ncontrols++;
 
462
 
 
463
  codec->nwidgets = wid + 1;
 
464
  widget = &codec->widgets[wid];
 
465
 
 
466
  widget->cad = cad;
 
467
  widget->wid = wid;
 
468
 
 
469
  widget->rgbcolor = 0;
 
470
 
 
471
  widget->group_type = group_type;
 
472
 
 
473
  DDB (cmn_err (CE_CONT, "   * Widget %02x, type %d\n", wid, group_type));
 
474
 
 
475
  if (!corb_read
 
476
      (mixer, cad, wid, 0, GET_PARAMETER, HDA_WIDGET_CAPS, &widget_caps, &b))
 
477
    {
 
478
      cmn_err (CE_WARN, "GET_PARAMETER HDA_WIDGET_CAPS failed\n");
 
479
      return 0;
 
480
    }
 
481
 
 
482
  if (widget_caps & WCAP_AMP_CAP_OVERRIDE)      /* Amp param override? */
 
483
    {
 
484
      if (!corb_read (mixer, widget->cad, widget->wid, 0,
 
485
                      GET_PARAMETER, HDA_OUTPUTAMP_CAPS, &outamp_caps, &b))
 
486
        {
 
487
          cmn_err (CE_WARN, "GET_PARAMETER HDA_OUTPUTAMP_CAPS failed\n");
 
488
          return -EIO;
 
489
        }
 
490
      widget->outamp_caps = outamp_caps;
 
491
 
 
492
      if (!corb_read (mixer, widget->cad, widget->wid, 0,
 
493
                      GET_PARAMETER, HDA_INPUTAMP_CAPS, &inamp_caps, &b))
 
494
        {
 
495
          cmn_err (CE_WARN, "GET_PARAMETER HDA_INPUTAMP_CAPS failed\n");
 
496
          return -EIO;
 
497
        }
 
498
      widget->inamp_caps = inamp_caps;
 
499
    }
 
500
  else
 
501
    {
 
502
      widget->outamp_caps = outamp_caps = codec->default_outamp_caps;
 
503
      widget->inamp_caps = inamp_caps = codec->default_inamp_caps;
 
504
    }
 
505
 
 
506
  if (!corb_read (mixer, cad, wid, 0, GET_POWER_STATE, 0, &pstate, &b))
 
507
    return 0;
 
508
 
 
509
  /* power up each of the widgets if there is a Power Capability (1<<10) */
 
510
  if (widget_caps & WCAP_POWER_CTL)
 
511
    corb_write (mixer, cad, wid, 0, SET_POWER_STATE, 0);
 
512
 
 
513
  widget->widget_caps = widget_caps;
 
514
 
 
515
  wid_type = (widget_caps >> 20) & 0x0f;
 
516
  DDB (cmn_err
 
517
       (CE_CONT, "\tWidget type %d (%s)(%s)\n", wid_type,
 
518
        widget_types[wid_type], widget_id[wid_type]));
 
519
  DDB (cmn_err (CE_CONT, "\tPower State %d\n", pstate));
 
520
 
 
521
  if (widget_caps & WCAP_CONN_LIST)
 
522
    {
 
523
      unsigned int clen;
 
524
      /* Handle connection list */
 
525
 
 
526
      if (!corb_read
 
527
          (mixer, cad, wid, 0, GET_PARAMETER, HDA_CONNLIST_LEN, &clen, &b))
 
528
        {
 
529
          cmn_err (CE_WARN, "GET_PARAMETER HDA_CONNLIST_LEN failed\n");
 
530
          return 0;
 
531
        }
 
532
 
 
533
      if (clen & 0x80)
 
534
        {
 
535
          cmn_err (CE_WARN, "Long form connection list not supported\n");
 
536
          return 0;
 
537
        }
 
538
 
 
539
      if (clen > 0)
 
540
        {
 
541
          if (clen > MAX_CONN)
 
542
            {
 
543
              cmn_err (CE_WARN, "Too many connections\n");
 
544
              return 0;
 
545
            }
 
546
 
 
547
          DDB (cmn_err (CE_CONT, "\tConn list (%d): ", clen));
 
548
 
 
549
          for (i = 0; i < clen; i += 4)
 
550
            {
 
551
              int j;
 
552
              unsigned int a;
 
553
 
 
554
              if (!corb_read
 
555
                  (mixer, cad, wid, 0, GET_CONNECTION_LIST_ENTRY, i, &a, &b))
 
556
                {
 
557
                  cmn_err (CE_WARN, "GET_CONNECTION_LIST_ENTRY failed\n");
 
558
                  return 0;
 
559
                }
 
560
 
 
561
              for (j = 0; j < 4 && (i + j) < clen; j++)
 
562
                {
 
563
                  int v, is_range = 0;
 
564
 
 
565
                  if (widget->nconn >= MAX_CONN)
 
566
                    {
 
567
                      cmn_err (CE_WARN,
 
568
                               "Too many connections for widget %d (%d)\n",
 
569
                               widget->wid, widget->nconn);
 
570
                      break;
 
571
                    }
 
572
 
 
573
                  v = (a >> (j * 8)) & 0xff;
 
574
                  DDB (cmn_err (CE_CONT, "%d ", v));
 
575
 
 
576
                  if (v & 0x80)
 
577
                    {
 
578
                      is_range = 1;
 
579
                      v &= ~0x80;
 
580
                    }
 
581
 
 
582
                  if (v < 0 || v >= MAX_WIDGETS)
 
583
                    {
 
584
                      cmn_err (CE_NOTE,
 
585
                               "Connection %d for widget %d is out of range (%d) - Skipped\n",
 
586
                               j, widget->wid, v);
 
587
                      continue;
 
588
                    }
 
589
 
 
590
                  if (is_range) /* Range: prev...v */
 
591
                    {
 
592
                      int x;
 
593
                      codec->widgets[v].references[codec->widgets[v].
 
594
                                                   refcount++] = wid;
 
595
 
 
596
                      if (widget->nconn < 1)
 
597
                        {
 
598
                          cmn_err (CE_CONT,
 
599
                                   "Bad range connection for widget %d\n",
 
600
                                   widget->wid);
 
601
                          continue;
 
602
                        }
 
603
 
 
604
                      for (x = widget->connections[widget->nconn - 1] + 1;
 
605
                           x <= v; x++)
 
606
                        {
 
607
                          if (widget->nconn >= MAX_CONN)
 
608
                            {
 
609
                              cmn_err (CE_WARN,
 
610
                                       "Too many connectionsi(B) for widget %d (%d)\n",
 
611
                                       widget->wid, widget->nconn);
 
612
                              break;
 
613
                            }
 
614
 
 
615
                          widget->connections[widget->nconn++] = x;
 
616
                          codec->widgets[x].references[codec->widgets[x].
 
617
                                                       refcount++] = wid;
 
618
                        }
 
619
                    }
 
620
                  else
 
621
                    {
 
622
                      widget->connections[widget->nconn++] = v;
 
623
                      codec->widgets[v].references[codec->widgets[v].
 
624
                                                   refcount++] = wid;
 
625
                    }
 
626
                }
 
627
            }
 
628
 
 
629
          DDB (cmn_err (CE_CONT, "\n"));
 
630
        }
 
631
    }
 
632
 
 
633
  widget->wid_type = wid_type;
 
634
  strcpy (widget->name, widget_id[wid_type]);
 
635
 
 
636
/*
 
637
 * Handle widget based on its type.
 
638
 */
 
639
 
 
640
  switch (wid_type)
 
641
    {
 
642
    case NT_PIN:
 
643
      if (!attach_pin_widget (mixer, codec, widget, cad, wid, group_type))
 
644
        return 0;
 
645
      break;
 
646
    }
 
647
 
 
648
  return 1;
 
649
}
 
650
 
 
651
 /*ARGSUSED*/ static int
 
652
attach_function_group (hdaudio_mixer_t * mixer, int cad, int wid,
 
653
                       int group_type)
 
654
{
 
655
  unsigned int a, b, gt;
 
656
  int i, first_node, num_nodes;
 
657
  codec_t *codec = mixer->codecs[cad];
 
658
 
 
659
  if (codec == NULL)
 
660
    return 0;
 
661
  cmn_err (CE_CONT, "Attach function group, cad=%02x, wid=%02x\n", cad, wid);
 
662
 
 
663
  if (!corb_read (mixer, cad, wid, 0,
 
664
                  GET_PARAMETER, HDA_OUTPUTAMP_CAPS,
 
665
                  &codec->default_outamp_caps, &b))
 
666
    {
 
667
      cmn_err (CE_WARN, "GET_PARAMETER HDA_OUTPUTAMP_CAPS failed\n");
 
668
      return 0;
 
669
    }
 
670
 
 
671
  if (!corb_read (mixer, cad, wid, 0,
 
672
                  GET_PARAMETER, HDA_INPUTAMP_CAPS,
 
673
                  &codec->default_inamp_caps, &b))
 
674
    {
 
675
      cmn_err (CE_WARN, "GET_PARAMETER HDA_INPUTTAMP_CAPS failed\n");
 
676
      return 0;
 
677
    }
 
678
 
 
679
  if (!corb_read (mixer, cad, wid, 0, GET_PARAMETER, HDA_NODE_COUNT, &a, &b))
 
680
    {
 
681
      cmn_err (CE_WARN, "GET_PARAMETER HDA_NODE_COUNT2 failed\n");
 
682
      return 0;
 
683
    }
 
684
 
 
685
  first_node = (a >> 16) & 0xff;
 
686
  num_nodes = a & 0xff;
 
687
 
 
688
  corb_read (mixer, cad, wid, 0, GET_PARAMETER, HDA_GROUP_TYPE, &gt, &b);
 
689
  gt &= 0xff;
 
690
 
 
691
  DDB (cmn_err
 
692
       (CE_CONT,
 
693
        " * Function group %d First node %d, num nodes %d, group type %x\n",
 
694
        wid, first_node, num_nodes, gt));
 
695
/*
 
696
 * Ignore other than audio function groups. Codecs probably allocate
 
697
 * higher widget number for the modem group than the audio group. So in this
 
698
 * way we can have smaller MAX_WIDGETS which in turn conserves memory.
 
699
 */
 
700
  if (gt != group_type)
 
701
    return 0;
 
702
 
 
703
  if (corb_read (mixer, cad, wid, 0, GET_PARAMETER, HDA_PCM_SIZES, &a, &b))
 
704
    {
 
705
      codec->sizes = a;
 
706
    }
 
707
 
 
708
  if (first_node > 0)
 
709
    for (i = first_node; i < first_node + num_nodes; i++)
 
710
      if (!attach_widget (mixer, cad, i, gt))
 
711
        return 0;
 
712
 
 
713
  if (num_nodes >= 1)
 
714
    codec->active = 1;
 
715
  return 1;
 
716
}
 
717
static int
 
718
attach_codec (hdaudio_mixer_t * mixer, int cad, char *hw_info,
 
719
              unsigned int pci_subdevice, int group_type)
 
720
{
 
721
  unsigned int a, b, x;
 
722
  int i;
 
723
  int first_node, num_nodes;
 
724
  int has_audio_group = 0;
 
725
  codec_t *codec;
 
726
 
 
727
  if (cad >= MAX_CODECS)
 
728
    {
 
729
      cmn_err (CE_WARN, "attach_codec: Too many codecs %d\n", cad);
 
730
      return -EIO;
 
731
    }
 
732
 
 
733
  mixer->ncodecs = cad + 1;
 
734
 
 
735
  if (mixer->codecs[cad] == NULL)
 
736
    {
 
737
      if ((codec = PMALLOC (mixer->osdev, sizeof (*codec))) == NULL)
 
738
        {
 
739
          cmn_err (CE_CONT, "Cannot allocate codec descriptor\n");
 
740
          return -ENOMEM;
 
741
        }
 
742
 
 
743
      memset (codec, 0, sizeof (*codec));
 
744
 
 
745
      mixer->codecs[cad] = codec;
 
746
    }
 
747
  else
 
748
    {
 
749
      codec = mixer->codecs[cad];
 
750
    }
 
751
 
 
752
  corb_write (mixer, cad, 0, 0, SET_POWER_STATE, 0);    /* Power up everything */
 
753
 
 
754
  if (!corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_VENDOR, &a, &b))
 
755
    {
 
756
      if (group_type == 1)
 
757
        {
 
758
          sprintf (hw_info, " Codec %2d: Not present\n", cad);
 
759
          cmn_err (CE_NOTE,
 
760
                   "attach_codec: Codec #%d is not physically present\n",
 
761
                   cad);
 
762
        }
 
763
      return -EIO;
 
764
    }
 
765
 
 
766
  codec->vendor_id = a;
 
767
 
 
768
/*
 
769
 * Find out the primary group list
 
770
 */
 
771
 
 
772
  if (!corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_NODE_COUNT, &x, &b))
 
773
    {
 
774
      cmn_err (CE_WARN, "GET_PARAMETER HDA_NODE_COUNT3 failed\n");
 
775
      return -EIO;
 
776
    }
 
777
 
 
778
  codec->first_node = first_node = (x >> 16) & 0xff;
 
779
  num_nodes = x & 0xff;
 
780
 
 
781
/*
 
782
 * Check if this one is an audio codec (has an audio function group)
 
783
 */
 
784
  for (i = first_node; i < first_node + num_nodes; i++)
 
785
    {
 
786
      unsigned int gt;
 
787
 
 
788
      if (corb_read
 
789
          (mixer, cad, i, 0, GET_PARAMETER, HDA_GROUP_TYPE, &gt, &b));
 
790
      if ((gt & 0xff) != 1)     /* Audio function group */
 
791
        continue;
 
792
 
 
793
      has_audio_group = 1;
 
794
    }
 
795
 
 
796
#if 0
 
797
/*
 
798
 * Find codec specific settings
 
799
 */
 
800
  for (ix = 0; codecs[ix].id != 0; ix++)
 
801
    if (codecs[ix].id == a)
 
802
      break;
 
803
 
 
804
  DDB (cmn_err
 
805
       (CE_CONT, "HD audio Codec ID: %08x (%s)\n", a, codecs[ix].name));
 
806
 
 
807
  if (codecs[ix].id == 0)       /* Unknown codec */
 
808
    {
 
809
      if (group_type == 1)
 
810
        sprintf (hw_info, " Codec %2d: Unknown (0x%08x", cad, a);
 
811
      cmn_err (CE_NOTE, "Unknown HDA codec 0x%08x\n", a);
 
812
      /* 
 
813
       * Create hexadecimal codec ID
 
814
       */
 
815
      if (has_audio_group && mixer->chip_name == NULL)
 
816
        if ((mixer->chip_name = PMALLOC (mixer->osdev, 32)) != NULL)
 
817
          {
 
818
            sprintf (mixer->chip_name, "0x%08x", a);
 
819
          }
 
820
    }
 
821
  else
 
822
    {
 
823
      if (group_type == 1)
 
824
        sprintf (hw_info, " Codec %2d: %s (0x%08x", cad, codecs[ix].name, a);
 
825
    }
 
826
 
 
827
  if (has_audio_group && mixer->chip_name == NULL)
 
828
    {
 
829
      mixer->chip_name = codecs[ix].name;
 
830
 
 
831
    }
 
832
 
 
833
  if (codecs[ix].remap != NULL)
 
834
    codec->remap = codecs[ix].remap;
 
835
 
 
836
  if (codecs[ix].flags != 0)
 
837
    codec->vendor_flags = codecs[ix].flags;
 
838
 
 
839
  if (codecs[ix].mixer_init != NULL)
 
840
    codec->mixer_init = codecs[ix].mixer_init;
 
841
 
 
842
  codec->multich_map = codecs[ix].multich_map;
 
843
  codec->codec_desc = &codecs[ix];
 
844
#endif
 
845
 
 
846
  if (corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_REVISION, &a, &b))
 
847
    {
 
848
      DDB (cmn_err (CE_CONT, "HDA codec revision %d.%d (%d.%d) (0x%08x)\n",
 
849
                    (a >> 20) & 0xf,
 
850
                    (a >> 16) & 0xf, (a >> 8) & 0xff, a & 0xff, a));
 
851
    }
 
852
  else
 
853
    DDB (cmn_err (CE_CONT, "Can't get codec revision\n"));
 
854
 
 
855
  DDB (cmn_err (CE_CONT, "**** Codec %d ****\n", cad));
 
856
  DDB (cmn_err
 
857
       (CE_CONT, "First group node %d, num nodes %d\n", first_node,
 
858
        num_nodes));
 
859
 
 
860
  for (i = first_node; i < first_node + num_nodes; i++)
 
861
    {
 
862
      corb_read (mixer, cad, i, 0, GET_PARAMETER, HDA_GROUP_TYPE, &a, &b);
 
863
      if ((a & 0xff) == group_type)     /* Proper function group type */
 
864
        {
 
865
          codec->afg = i;
 
866
 
 
867
          if (corb_read (mixer, cad, i, 0, GET_SUBSYSTEM_ID, 0, &a, &b))
 
868
            {
 
869
              DDB (cmn_err (CE_CONT, "Subsystem ID = 0x%08x\n", a));
 
870
 
 
871
              if (group_type == 1)
 
872
                {
 
873
                  /* Append subvendor ID to hw_info */
 
874
                  hw_info += strlen (hw_info);
 
875
                  sprintf (hw_info, "/0x%08x", a);
 
876
                }
 
877
 
 
878
              codec->subvendor_id = a;
 
879
 
 
880
#if 0
 
881
              for (subix = 0; subdevices[subix].id != 0; subix++)
 
882
                if (subdevices[subix].id == a)
 
883
                  {
 
884
                    if (subdevices[subix].main_id != 0)
 
885
                      if (subdevices[subix].main_id != codec->vendor_id)
 
886
                        continue;
 
887
 
 
888
                    if (subdevices[subix].pci_subdevice != 0)
 
889
                      if (subdevices[subix].pci_subdevice != pci_subdevice)
 
890
                        continue;
 
891
 
 
892
 
 
893
                    DDB (cmn_err
 
894
                         (CE_CONT, "Subdevice known as %s\n",
 
895
                          subdevices[subix].name));
 
896
                    if (group_type == 1)
 
897
                      {
 
898
                        hw_info += strlen (hw_info);
 
899
                        sprintf (hw_info, " %s", subdevices[subix].name);
 
900
                      }
 
901
                    if (subdevices[subix].remap != NULL)
 
902
                      {
 
903
                        codec->remap = subdevices[subix].remap;
 
904
                      }
 
905
 
 
906
                    if (subdevices[subix].multich_map != 0)
 
907
                      codec->multich_map = subdevices[subix].multich_map;
 
908
                    if (subdevices[subix].flags != 0)
 
909
                      codec->vendor_flags = subdevices[subix].flags;
 
910
                    if (subdevices[subix].mixer_init != NULL)
 
911
                      {
 
912
                        codec->mixer_init = subdevices[subix].mixer_init;
 
913
                      }
 
914
                  }
 
915
#endif
 
916
            }
 
917
          break;
 
918
        }
 
919
    }
 
920
 
 
921
  hw_info += strlen (hw_info);
 
922
  if (group_type == 1)
 
923
    strcpy (hw_info, ")\n");
 
924
 
 
925
  for (i = first_node; i < first_node + num_nodes; i++)
 
926
    {
 
927
      if (!attach_function_group (mixer, cad, i, group_type))
 
928
        continue;
 
929
 
 
930
      /* power up the AFG! */
 
931
      corb_write (mixer, cad, i, 0, SET_POWER_STATE, 0);
 
932
    }
 
933
 
 
934
#if 0
 
935
  if (has_audio_group)
 
936
    {
 
937
      polish_widget_list (mixer, cad);
 
938
    }
 
939
 
 
940
  copy_endpoints (mixer, codec, 0);     /* Copy analog endpoints from codec to mixer */
 
941
#endif
 
942
 
 
943
  return (has_audio_group) ? 0 : -EIO;
 
944
}
 
945
 
 
946
static void
 
947
follow_path(hdaudio_mixer_t *mixer, codec_t *codec, widget_t *widget, path_t *path, int use_force)
 
948
{
 
949
  int i;
 
950
 
 
951
  if (widget->used)
 
952
     return;
 
953
 
 
954
  widget->used = 1;
 
955
  path->widgets[path->nwidgets++] = widget;
 
956
  if (widget->wid_type == NT_PIN)
 
957
  {
 
958
        path->jack_count++;
 
959
        path->association=widget->association;
 
960
        path->sequence=widget->sequence;
 
961
 
 
962
        /*
 
963
         * Stop at a pin widget that is not the first widget of the path.
 
964
         * In this way we don't walk back the input chain from the pin.
 
965
         */
 
966
 
 
967
        if (path->nwidgets > 1)
 
968
           return;
 
969
  }
 
970
 
 
971
  if (use_force || path->nwidgets == 1 || widget->nconn == 1 || (widget->nconn>0 && widget->wid_type == NT_SELECT))
 
972
  {
 
973
     for (i=0;i<widget->nconn;i++)
 
974
     if (!codec->widgets[widget->connections[i]].used)
 
975
     //if (codec->widgets[widget->connections[i]].refcount < 2)
 
976
     {
 
977
        follow_path(mixer, codec, &codec->widgets[widget->connections[i]], path, use_force);
 
978
        return;
 
979
     }
 
980
  }
 
981
}
 
982
 
 
983
static void
 
984
dump_path(hdaudio_mixer_t *mixer, path_t *path)
 
985
{
 
986
        int i, j;
 
987
 
 
988
        if (path->nwidgets == 0)
 
989
           return;
 
990
 
 
991
        printf("Path (a=%x, s=%x, jc=%d):\n ", path->association, path->sequence, path->jack_count);
 
992
 
 
993
        for (i=0;i<path->nwidgets;i++)
 
994
        {
 
995
            widget_t *widget = path->widgets[i];
 
996
 
 
997
            printf("\t%02x(%s/%s/nc=%d/rc=%d", widget->wid, widget_id[widget->wid_type], widget->name, widget->nconn, widget->refcount);
 
998
            printf(")\n");
 
999
 
 
1000
            if (widget->widget_caps & WCAP_OUTPUT_AMP_PRESENT)
 
1001
               {
 
1002
                       printf("\t\tOutput amp\n");
 
1003
               }
 
1004
 
 
1005
            if (widget->widget_caps & WCAP_INPUT_AMP_PRESENT)
 
1006
               {
 
1007
                       printf("\t\t%d input amp(s)\n", widget->nconn);
 
1008
 
 
1009
                       for (j=0;j<widget->nconn;j++)
 
1010
                       {
 
1011
                          widget_t *in_widget;
 
1012
 
 
1013
                          in_widget = &mixer->codecs[widget->cad]->
 
1014
                                        widgets[widget->connections[j]];
 
1015
            printf("\t\t\t%02x(%s/%s/nc=%d/rc=%d)\n", in_widget->wid, widget_id[in_widget->wid_type], in_widget->name, in_widget->nconn, in_widget->refcount);
 
1016
 
 
1017
                          in_widget->used=1;
 
1018
                       }
 
1019
               }
 
1020
        }
 
1021
        printf("\n");
 
1022
}
 
1023
 
 
1024
static void
 
1025
store_path(hdaudio_mixer_t *mixer, path_t *path)
 
1026
{
 
1027
        if (npaths>=MAX_PATHS)
 
1028
        {
 
1029
                cmn_err(CE_WARN, "Too many paths\n");
 
1030
                return;
 
1031
        }
 
1032
 
 
1033
        paths[npaths++]=path;
 
1034
}
 
1035
 
 
1036
static void
 
1037
create_path_list(hdaudio_mixer_t *mixer, int cad, int node_type, int use_force)
 
1038
{
 
1039
  codec_t *codec;
 
1040
  int wid;
 
1041
 
 
1042
  path_t *path;
 
1043
 
 
1044
cmn_err(CE_CONT, "Create path list %d (%s)\n", node_type, widget_id[node_type]);
 
1045
  codec=mixer->codecs[cad];
 
1046
 
 
1047
  for (wid=0;wid<codec->nwidgets;wid++)
 
1048
  if (codec->widgets[wid].wid_type == node_type)
 
1049
  if (!codec->widgets[wid].skip)
 
1050
  if (codec->widgets[wid].wid == wid)
 
1051
  {
 
1052
          path=malloc(sizeof(*path));
 
1053
 
 
1054
          follow_path(mixer, codec, &codec->widgets[wid], path, use_force);
 
1055
 
 
1056
          if (path->nwidgets>1)
 
1057
             store_path(mixer, path);
 
1058
          else
 
1059
             if (path->nwidgets>0)
 
1060
                path->widgets[0]->used=0;
 
1061
  }
 
1062
 
 
1063
}
 
1064
 
 
1065
static void
 
1066
create_path_list_for_pin(hdaudio_mixer_t *mixer, int cad, int association, int sequence)
 
1067
{
 
1068
  codec_t *codec;
 
1069
  int wid;
 
1070
 
 
1071
  path_t *path;
 
1072
 
 
1073
  codec=mixer->codecs[cad];
 
1074
 
 
1075
  for (wid=0;wid<codec->nwidgets;wid++)
 
1076
  if (codec->widgets[wid].wid_type == NT_PIN && !codec->widgets[wid].skip)
 
1077
  if (codec->widgets[wid].pin_type == PIN_HEADPHONE || codec->widgets[wid].pin_type == PIN_OUT)
 
1078
  if (codec->widgets[wid].wid == wid)
 
1079
  if (codec->widgets[wid].nconn > 0)
 
1080
  if (!codec->widgets[wid].skip)
 
1081
  if (codec->widgets[wid].sequence == sequence)
 
1082
  if (codec->widgets[wid].association == association)
 
1083
  {
 
1084
          path=malloc(sizeof(*path));
 
1085
 
 
1086
          follow_path(mixer, codec, &codec->widgets[wid], path, 0);
 
1087
 
 
1088
          if (path->nwidgets>1)
 
1089
             store_path(mixer, path);
 
1090
          else
 
1091
             if (path->nwidgets>0)
 
1092
                path->widgets[0]->used=0;
 
1093
  }
 
1094
 
 
1095
}
 
1096
 
 
1097
hdaudio_mixer_t *
 
1098
hdaudio_mixer_create (char *name, void *devc,
 
1099
                      oss_device_t * osdev,
 
1100
                      hdmixer_write_t writefunc,
 
1101
                      hdmixer_read_t readfunc, unsigned int codecmask,
 
1102
                      unsigned int vendor_id, unsigned int subvendor_id)
 
1103
{
 
1104
  hdaudio_mixer_t *mixer;
 
1105
  int i, func;
 
1106
  int ncodecs = 0;
 
1107
  char tmp[128];
 
1108
  int mixer_dev;
 
1109
 
 
1110
  char *hw_info = osdev->hw_info;       /* For printing hardware information */
 
1111
 
 
1112
  if ((mixer = PMALLOC (osdev, sizeof (*mixer))) == NULL)
 
1113
    {
 
1114
      cmn_err (CE_WARN, "hdaudio_mixer_create: Out of memory\n");
 
1115
      return NULL;
 
1116
    }
 
1117
 
 
1118
  memset (mixer, 0, sizeof (*mixer));
 
1119
 
 
1120
  mixer->devc = devc;
 
1121
  mixer->osdev = osdev;
 
1122
  mixer->mixer_dev = 0;
 
1123
  strncpy (mixer->name, name, sizeof (mixer->name) - 1);
 
1124
  mixer->name[sizeof (mixer->name) - 1] = 0;
 
1125
 
 
1126
  for (i = 0; i < MAX_CODECS; i++)
 
1127
    mixer->codecs[i] = NULL;
 
1128
 
 
1129
#ifdef _KERNEL
 
1130
  mixer->read = readfunc;
 
1131
  mixer->write = writefunc;
 
1132
#endif
 
1133
 
 
1134
  mixer->codecmask = codecmask;
 
1135
 
 
1136
  sprintf (hw_info, "HD Audio controller %s\n"
 
1137
           "Vendor ID    0x%08x\n"
 
1138
           "Subvendor ID 0x%08x\n", name, vendor_id, subvendor_id);
 
1139
  hw_info += strlen (hw_info);
 
1140
 
 
1141
/*
 
1142
 * Search first all audio function groups for all codecs and then
 
1143
 * handle modem function groups.
 
1144
 */
 
1145
  for (func = 1; func <= 2; func++)
 
1146
    for (i = 0; i < 16; i++)
 
1147
      if (mixer->codecmask & (1 << i))
 
1148
        {
 
1149
          if (attach_codec (mixer, i, hw_info, subvendor_id, func) >= 0)
 
1150
            ncodecs++;
 
1151
          hw_info += strlen (hw_info);
 
1152
        }
 
1153
 
 
1154
  for (i = 0; i < 16; i++)
 
1155
  if (mixer->codecmask & (1 << i))
 
1156
  {
 
1157
     int association, sequence;
 
1158
 
 
1159
printf("*** Codec %d\n", i);
 
1160
     for (association=1;association<16;association++)
 
1161
     for (sequence=0;sequence<16;sequence++)
 
1162
         create_path_list_for_pin(mixer, i, association, sequence);
 
1163
 
 
1164
     create_path_list(mixer, i, NT_ADC, 0);
 
1165
     create_path_list(mixer, i, NT_MIXER, 1);
 
1166
     create_path_list(mixer, i, NT_SELECT, 1);
 
1167
  }
 
1168
 
 
1169
  for (i=0;i<npaths;i++)
 
1170
      dump_path(mixer, paths[i]);
 
1171
 
 
1172
#if 1
 
1173
  printf("\n\nOther widgets:\n");
 
1174
 
 
1175
  for (i = 0; i < 16; i++)
 
1176
  if (mixer->codecmask & (1 << i))
 
1177
  {
 
1178
        int wid;
 
1179
 
 
1180
        for (wid=0;wid<mixer->codecs[i]->nwidgets;wid++)
 
1181
        {
 
1182
                widget_t *widget = &mixer->codecs[i]->widgets[wid];
 
1183
 
 
1184
                if (widget->wid != wid)
 
1185
                   continue;
 
1186
 
 
1187
                if (widget->used || widget->skip)
 
1188
                   continue;
 
1189
            printf("Codec %d, Widget %02x %s/%s/%d\n", widget->cad, widget->wid, widget_id[widget->wid_type], widget->name, widget->nconn);
 
1190
        }
 
1191
  }
 
1192
#endif
 
1193
 
 
1194
  return mixer;
 
1195
}
 
1196
 
 
1197
int
 
1198
main (int argc, char *argv[])
 
1199
{
 
1200
  unsigned int rev, b;
 
1201
  int first_node, num_nodes;
 
1202
  int i;
 
1203
  int cad = 0;
 
1204
 
 
1205
  int codecmask = 0;
 
1206
 
 
1207
  oss_device_t osdev = { 0 };
 
1208
 
 
1209
  osdev.hw_info = malloc (256);
 
1210
 
 
1211
  if ((fd = open ("/dev/oss/oss_hdaudio0/pcm0", O_RDWR | O_EXCL, 0)) == -1)
 
1212
    {
 
1213
      perror ("/dev/oss/oss_hdaudio0/pcm0");
 
1214
      exit (-1);
 
1215
    }
 
1216
 
 
1217
  for (cad = 0; cad < 15; cad++)
 
1218
    if (corb_read (NULL, cad, 0, 0, GET_PARAMETER, HDA_REVISION, &rev, &b))
 
1219
      {
 
1220
#if 1
 
1221
        printf ("Codec %2d: HD codec revision %d.%d (%d.%d) (0x%08x)\n", cad,
 
1222
                (rev >> 20) & 0xf, (rev >> 16) & 0xf, (rev >> 8) & 0xff,
 
1223
                rev & 0xff, rev);
 
1224
#endif
 
1225
        codecmask |= (1 << cad);
 
1226
      }
 
1227
 
 
1228
  hdaudio_mixer_create ("ACME hdaudio", NULL,
 
1229
                        &osdev, NULL, NULL, codecmask, 0x12345678, 0x8754321);
 
1230
 
 
1231
  //printf("HW Info: %s\n", osdev.hw_info);
 
1232
  exit (0);
 
1233
}