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

« back to all changes in this revision

Viewing changes to kernel/drv/oss_envy24/envy24_1010lt.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
 * Purpose: Card specific routines for M Audio Delta 1010LT
 
3
 */
 
4
/*
 
5
 *
 
6
 * This file is part of Open Sound System.
 
7
 *
 
8
 * Copyright (C) 4Front Technologies 1996-2008.
 
9
 *
 
10
 * This this source file is released under GPL v2 license (no other versions).
 
11
 * See the COPYING file included in the main directory of this source
 
12
 * distribution for the license terms and conditions.
 
13
 *
 
14
 */
 
15
 
 
16
#include "oss_config.h"
 
17
#include <ac97.h>
 
18
#include "envy24.h"
 
19
 
 
20
#define CH_STEREO       0x80
 
21
 
 
22
/* SPI chip select codes */
 
23
#define CS8_CS 0x4
 
24
#define CDC_CS 0x0
 
25
#define NONE_CS 0x7
 
26
 
 
27
#define SPI_CLK 1
 
28
#define SPI_DIN 2
 
29
#define SPI_DOUT 3
 
30
#define WCLOCK_ENABLE 7
 
31
 
 
32
#define CS8_ADDR 0x20           /* Chip SPI/I2C address */
 
33
#define CS8_RD 0x01
 
34
#define CS8_WR 0x00
 
35
 
 
36
#define BIT0            0x01
 
37
#define BIT1            0x02
 
38
#define BIT2            0x04
 
39
#define BIT3            0x08
 
40
#define BIT4            0x10
 
41
#define BIT5            0x20
 
42
#define BIT6            0x40
 
43
#define BIT7            0x80
 
44
 
 
45
#if 0
 
46
# define PRT_STATUS(v) outb(v&0xff, 0x378)
 
47
#else
 
48
# define PRT_STATUS(v)
 
49
#endif
 
50
 
 
51
/* -----        DEFINITION OF GPIOs     ----- */
 
52
 
 
53
#define FPGA_PROGRAM_L          7       /* FPGA program control select line (active low) */
 
54
#define FPGA_CLK                1       /* FPGA program clock */
 
55
#define EXT_REG_CLK             0       /* Was GPIO Fast mode (debug) */
 
56
#define FPGA_D0                 3       /* FPGA program data */
 
57
 
 
58
#define LATCH_EN_L              4       /* Strobe for external latch (active low) */
 
59
#define FPGA_MUTE               5
 
60
 
 
61
#define FPGA_INIT_STATE 0xFC    /* Init state for extern register to allow */
 
62
                                /* FPGA initialization. */
 
63
 
 
64
#define FPGA_MASTER             5
 
65
 
 
66
extern int envy24_gain_sliders;
 
67
extern int envy24_virtualout;
 
68
extern int envy24_zerolatency;  /* Testing in progress */
 
69
 
 
70
static void
 
71
SPI_select (envy24_devc * devc, int sel)
 
72
{
 
73
  int tmp;
 
74
 
 
75
  tmp = envy24_read_cci (devc, 0x20);
 
76
  tmp &= ~0x70;
 
77
  tmp |= (sel & 0x7) << 4;
 
78
  envy24_write_cci (devc, 0x20, tmp);
 
79
}
 
80
 
 
81
static void
 
82
write_d1010lt_codec (envy24_devc * devc, int sel, int bRegister,
 
83
                     unsigned char bData)
 
84
{
 
85
  int bMask;
 
86
 
 
87
  WriteGPIObit (devc, SPI_DOUT, 0);
 
88
  WriteGPIObit (devc, SPI_CLK, 1);
 
89
 
 
90
  SPI_select (devc, sel);
 
91
  oss_udelay (1);
 
92
  bRegister = (bRegister & 0x0F) | 0xA0;        /* Add I2C address field. */
 
93
 
 
94
  /* Assert the CODEC chip select and wait at least 150 nS. */
 
95
  /* */
 
96
 
 
97
  /* Write the register address byte. */
 
98
  /* */
 
99
  for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F)
 
100
    {
 
101
      /* Drop SPI clock low. */
 
102
      WriteGPIObit (devc, SPI_CLK, 0);
 
103
 
 
104
      /* Write current data bit. */
 
105
      if (bMask & bRegister)
 
106
        WriteGPIObit (devc, SPI_DOUT, 1);
 
107
      else
 
108
        WriteGPIObit (devc, SPI_DOUT, 0);
 
109
 
 
110
      /* Raise SPI clock to "clock data in". */
 
111
      WriteGPIObit (devc, SPI_CLK, 1);
 
112
    }
 
113
 
 
114
 
 
115
  /* Write the data byte. */
 
116
  /* */
 
117
  for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F)
 
118
    {
 
119
      /* Drop SPI clock low. */
 
120
      WriteGPIObit (devc, SPI_CLK, 0);
 
121
 
 
122
      /* Write current data bit. */
 
123
      if (bMask & bData)
 
124
        WriteGPIObit (devc, SPI_DOUT, 1);
 
125
      else
 
126
        WriteGPIObit (devc, SPI_DOUT, 0);
 
127
 
 
128
      /* Raise SPI clock to "clock data in". */
 
129
      WriteGPIObit (devc, SPI_CLK, 1);
 
130
    }
 
131
 
 
132
  /* De-assert chip select. */
 
133
  /* */
 
134
 
 
135
  SPI_select (devc, NONE_CS);
 
136
}
 
137
 
 
138
static void
 
139
d1010lt_card_init (envy24_devc * devc)
 
140
{
 
141
  int i;
 
142
 
 
143
  SPI_select (devc, NONE_CS);
 
144
 
 
145
  for (i = 0; i < 4; i++)
 
146
    {
 
147
      write_d1010lt_codec (devc, i, 0, 0x07);
 
148
      write_d1010lt_codec (devc, i, 1, 0x03);
 
149
      write_d1010lt_codec (devc, i, 2, 0x60);
 
150
      write_d1010lt_codec (devc, i, 3, 0x19);
 
151
      write_d1010lt_codec (devc, i, 4, 0x7f);
 
152
      write_d1010lt_codec (devc, i, 5, 0x7f);
 
153
      write_d1010lt_codec (devc, i, 6, 0x7f);
 
154
      write_d1010lt_codec (devc, i, 7, 0x7f);
 
155
    }
 
156
 
 
157
}
 
158
 
 
159
static int
 
160
envy24_set_d1010lt (int dev, int ctrl, unsigned int cmd, int value)
 
161
{
 
162
  envy24_devc *devc = mixer_devs[dev]->devc;
 
163
  int codec, level;
 
164
  static unsigned char levels[] = { 0x7f, 0x8c, 0x98 };
 
165
 
 
166
  if (ctrl >= 0xff)
 
167
    return OSS_EINVAL;
 
168
 
 
169
  if (cmd == SNDCTL_MIX_READ)
 
170
    {
 
171
      return devc->akm_gains[ctrl];
 
172
    }
 
173
  else if (cmd == SNDCTL_MIX_WRITE)
 
174
    {
 
175
      codec = (ctrl & 0x7) / 2;
 
176
      if (envy24_gain_sliders)
 
177
        {
 
178
          level = value & 0xff;
 
179
          if (level < 0)
 
180
            level = 0;
 
181
          if (level > 144)
 
182
            level = 144;
 
183
        }
 
184
      else
 
185
        {
 
186
          if (value < 0 || value > 2)
 
187
            value = 0;
 
188
          level = levels[value];
 
189
        }
 
190
 
 
191
      switch (ctrl & 0x89)      /* IN/OUT, LEFT/RIGHT, Gang switches */
 
192
        {
 
193
        case 0x00:              /* Left output channel only */
 
194
          write_d1010lt_codec (devc, codec, 6, level);
 
195
          break;
 
196
 
 
197
        case 0x01:              /* Right output channel only */
 
198
          write_d1010lt_codec (devc, codec, 7, level);
 
199
          break;
 
200
 
 
201
        case 0x80:              /* Both output channels */
 
202
          write_d1010lt_codec (devc, codec, 6, level);
 
203
          write_d1010lt_codec (devc, codec, 7, level);
 
204
          break;
 
205
 
 
206
        case 0x08:              /* Left input channel only */
 
207
          write_d1010lt_codec (devc, codec, 4, level);
 
208
          break;
 
209
 
 
210
        case 0x09:              /* Right input channel only */
 
211
          write_d1010lt_codec (devc, codec, 5, level);
 
212
          break;
 
213
 
 
214
        case 0x88:              /* Both input channels */
 
215
          write_d1010lt_codec (devc, codec, 4, level);
 
216
          write_d1010lt_codec (devc, codec, 5, level);
 
217
          break;
 
218
        }
 
219
 
 
220
      return devc->akm_gains[ctrl] = value;
 
221
    }
 
222
  return OSS_EINVAL;
 
223
}
 
224
 
 
225
 
 
226
static int
 
227
d1010lt_mix_init (envy24_devc * devc, int dev, int group)
 
228
{
 
229
  int i, mask = devc->outportmask, err, skip;
 
230
  int typ = MIXT_ENUM, range = 3;
 
231
  char tmp[64];
 
232
 
 
233
  if ((group = mixer_ext_create_group (dev, 0, "ENVY24_GAIN")) < 0)
 
234
    return group;
 
235
 
 
236
  skip = devc->skipdevs;
 
237
  if (skip != 2)
 
238
    skip = 1;
 
239
 
 
240
  if (envy24_gain_sliders)
 
241
    {
 
242
      typ = MIXT_MONOSLIDER;
 
243
      range = 144;
 
244
 
 
245
      for (i = 0; i < 0xff; i++)
 
246
        devc->akm_gains[i] = 0x7f;
 
247
    }
 
248
  else
 
249
    for (i = 0; i < 0xff; i++)
 
250
      devc->akm_gains[i] = 0;
 
251
 
 
252
  for (i = 0; i < 8; i += skip)
 
253
    {
 
254
 
 
255
      if (!(mask & (1 << i)))
 
256
        continue;               /* Not present */
 
257
 
 
258
      if (devc->skipdevs == 2)
 
259
        {
 
260
          if (i == 8)
 
261
            strcpy (tmp, "ENVY24_SPDOUT");
 
262
          else
 
263
            sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2);
 
264
 
 
265
          if ((err = mixer_ext_create_control (dev, group,
 
266
                                               i | CH_STEREO,
 
267
                                               envy24_set_d1010lt, typ, tmp,
 
268
                                               range,
 
269
                                               MIXF_MAINVOL |
 
270
                                               MIXF_READABLE |
 
271
                                               MIXF_WRITEABLE)) < 0)
 
272
            return err;
 
273
        }
 
274
      else
 
275
        {
 
276
          if (i == 8)
 
277
            strcpy (tmp, "ENVY24_SPDOUTL");
 
278
          else if (i == 9)
 
279
            strcpy (tmp, "ENVY24_SPDOUTR");
 
280
          else
 
281
            sprintf (tmp, "ENVY24_OUT%d", i + 1);
 
282
 
 
283
          if ((err = mixer_ext_create_control (dev, group,
 
284
                                               i, envy24_set_d1010lt,
 
285
                                               typ,
 
286
                                               tmp, range,
 
287
                                               MIXF_MAINVOL |
 
288
                                               MIXF_READABLE |
 
289
                                               MIXF_WRITEABLE)) < 0)
 
290
            return err;
 
291
        }
 
292
    }
 
293
 
 
294
  mask = devc->inportmask;
 
295
  for (i = 0; i < 8; i += skip)
 
296
    {
 
297
 
 
298
      if (!(mask & (1 << i)))
 
299
        continue;               /* Not present */
 
300
 
 
301
      if (devc->skipdevs == 2)
 
302
        {
 
303
          if (i == 8)
 
304
            strcpy (tmp, "ENVY24_SPDIN");
 
305
          else
 
306
            sprintf (tmp, "ENVY24_IN%d/%d", i + 1, i + 2);
 
307
 
 
308
          if ((err = mixer_ext_create_control (dev, group,
 
309
                                               (8 + i) | CH_STEREO,
 
310
                                               envy24_set_d1010lt, typ, tmp,
 
311
                                               range,
 
312
                                               MIXF_RECVOL |
 
313
                                               MIXF_READABLE |
 
314
                                               MIXF_WRITEABLE)) < 0)
 
315
            return err;
 
316
        }
 
317
      else
 
318
        {
 
319
          if (i == 8)
 
320
            strcpy (tmp, "ENVY24_SPDINL");
 
321
          else if (i == 9)
 
322
            strcpy (tmp, "ENVY24_SPDINR");
 
323
          else
 
324
            sprintf (tmp, "ENVY24_IN%d", i + 1);
 
325
 
 
326
          if ((err = mixer_ext_create_control (dev, group,
 
327
                                               8 + i, envy24_set_d1010lt,
 
328
                                               typ,
 
329
                                               tmp, range,
 
330
                                               MIXF_RECVOL |
 
331
                                               MIXF_READABLE |
 
332
                                               MIXF_WRITEABLE)) < 0)
 
333
            return err;
 
334
        }
 
335
    }
 
336
 
 
337
  return 0;
 
338
}
 
339
 
 
340
static void
 
341
write_d1010lt_spdif_reg (envy24_devc * devc, int bRegister, int bData)
 
342
{
 
343
  unsigned char bMask;
 
344
  unsigned char bSPI;
 
345
 
 
346
  /* Assert the CODEC chip select and wait at least 150 nS. */
 
347
  /* */
 
348
  SPI_select (devc, CS8_CS);
 
349
 
 
350
  /* Write the SPI address/cmd byte. */
 
351
  /* */
 
352
  bSPI = CS8_ADDR | CS8_WR;
 
353
  /* */
 
354
  for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F)
 
355
    {
 
356
      /* Drop SPI clock low. */
 
357
      WriteGPIObit (devc, SPI_CLK, 0);
 
358
 
 
359
      /* Write current data bit. */
 
360
      if (bMask & bSPI)
 
361
        WriteGPIObit (devc, SPI_DOUT, 1);
 
362
      else
 
363
        WriteGPIObit (devc, SPI_DOUT, 0);
 
364
 
 
365
      /* Raise SPI clock to "clock data in". */
 
366
      WriteGPIObit (devc, SPI_CLK, 1);
 
367
    }
 
368
 
 
369
  /* Write the address (MAP) byte. */
 
370
  /* */
 
371
  for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F)
 
372
    {
 
373
      /* Drop SPI clock low. */
 
374
      WriteGPIObit (devc, SPI_CLK, 0);
 
375
 
 
376
      /* Write current data bit. */
 
377
      if (bMask & bRegister)
 
378
        WriteGPIObit (devc, SPI_DOUT, 1);
 
379
      else
 
380
        WriteGPIObit (devc, SPI_DOUT, 0);
 
381
 
 
382
      /* Raise SPI clock to "clock data in". */
 
383
      WriteGPIObit (devc, SPI_CLK, 1);
 
384
    }
 
385
 
 
386
 
 
387
  /* Write the data byte. */
 
388
  /* */
 
389
  for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F)
 
390
    {
 
391
      /* Drop SPI clock low. */
 
392
      WriteGPIObit (devc, SPI_CLK, 0);
 
393
 
 
394
      /* Write current data bit. */
 
395
      if (bMask & bData)
 
396
        WriteGPIObit (devc, SPI_DOUT, 1);
 
397
      else
 
398
        WriteGPIObit (devc, SPI_DOUT, 0);
 
399
 
 
400
      /* Raise SPI clock to "clock data in". */
 
401
      WriteGPIObit (devc, SPI_CLK, 1);
 
402
    }
 
403
 
 
404
  /* De-assert chip select. */
 
405
  /* */
 
406
  SPI_select (devc, NONE_CS);
 
407
}
 
408
 
 
409
static int
 
410
read_d1010lt_spdif_reg (envy24_devc * devc, int reg)
 
411
{
 
412
  unsigned char bMask;
 
413
  unsigned char bRet = 0;
 
414
  unsigned char bSPI;
 
415
 
 
416
 
 
417
        /****** WRITE MAP ADDRESS FIRST ******/
 
418
 
 
419
  /* Drop the chip select low. */
 
420
  /* Wait at least 150 nS. */
 
421
  /* */
 
422
  SPI_select (devc, CS8_CS);
 
423
 
 
424
  /* Write the SPI address/cmd byte. */
 
425
  /* */
 
426
  bSPI = CS8_ADDR + CS8_WR;     /* SPI address field plus WRITE operation. */
 
427
  /* */
 
428
  for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F)
 
429
    {
 
430
      /* Drop clock (GPIO5) low. */
 
431
      WriteGPIObit (devc, SPI_CLK, 0);
 
432
 
 
433
      /* Write current data bit. */
 
434
      if (bMask & bSPI)
 
435
        WriteGPIObit (devc, SPI_DOUT, 1);
 
436
      else
 
437
        WriteGPIObit (devc, SPI_DOUT, 0);
 
438
 
 
439
      /* Raise clock (GPIO5). */
 
440
      WriteGPIObit (devc, SPI_CLK, 1);
 
441
    }
 
442
 
 
443
 
 
444
  /* Write the address (MAP) byte. */
 
445
  /* */
 
446
  for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F)
 
447
    {
 
448
      /* Drop clock (GPIO5) low. */
 
449
      WriteGPIObit (devc, SPI_CLK, 0);
 
450
 
 
451
      /* Write current data bit. */
 
452
      if (bMask & reg)
 
453
        WriteGPIObit (devc, SPI_DOUT, 1);
 
454
      else
 
455
        WriteGPIObit (devc, SPI_DOUT, 0);
 
456
 
 
457
      /* Raise clock (GPIO5). */
 
458
      WriteGPIObit (devc, SPI_CLK, 1);
 
459
    }
 
460
 
 
461
  /* De-assert chip select(s). */
 
462
  /* */
 
463
  SPI_select (devc, NONE_CS);
 
464
 
 
465
 
 
466
        /****** NOW READ THE DATA ******/
 
467
 
 
468
  /* Drop the chip select low. */
 
469
  /* Wait at least 150 nS. */
 
470
  /* */
 
471
  SPI_select (devc, CS8_CS);
 
472
 
 
473
 
 
474
  /* Write the SPI address/cmd byte. */
 
475
  /* */
 
476
  bSPI = CS8_ADDR + CS8_RD;     /* SPI address field plus READ operation. */
 
477
  /* */
 
478
  for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F)
 
479
    {
 
480
      /* Drop clock (GPIO5) low. */
 
481
      WriteGPIObit (devc, SPI_CLK, 0);
 
482
 
 
483
      /* Write current data bit. */
 
484
      if (bMask & bSPI)
 
485
        WriteGPIObit (devc, SPI_DOUT, 1);
 
486
      else
 
487
        WriteGPIObit (devc, SPI_DOUT, 0);
 
488
 
 
489
      /* Raise clock (GPIO5). */
 
490
      WriteGPIObit (devc, SPI_CLK, 1);
 
491
    }
 
492
 
 
493
 
 
494
  /* Read the data byte. */
 
495
  /* */
 
496
  bRet = 0;
 
497
  /* */
 
498
  for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F)
 
499
    {
 
500
      /* Drop clock low. */
 
501
      WriteGPIObit (devc, SPI_CLK, 0);
 
502
 
 
503
      /* Read current data bit. */
 
504
      if (ReadGPIObit (devc, SPI_DIN))
 
505
        bRet |= bMask;
 
506
 
 
507
      /* Raise clock. */
 
508
      WriteGPIObit (devc, SPI_CLK, 1);
 
509
    }
 
510
 
 
511
 
 
512
  /* De-assert chip selects. */
 
513
  /* */
 
514
  SPI_select (devc, NONE_CS);
 
515
 
 
516
  /* Return value. */
 
517
 
 
518
  return bRet;
 
519
}
 
520
 
 
521
static void
 
522
set_d1010lt_speed (envy24_devc * devc)
 
523
{
 
524
  int tmp;
 
525
 
 
526
  tmp = devc->speedbits;
 
527
 
 
528
  switch (devc->syncsource)
 
529
    {
 
530
    case SYNC_INTERNAL:
 
531
      OUTB (devc->osdev, tmp, devc->mt_base + 0x01);
 
532
      WriteGPIObit (devc, WCLOCK_ENABLE, 0);
 
533
      write_d1010lt_spdif_reg (devc, 4,
 
534
                               read_d1010lt_spdif_reg (devc, 4) & (~BIT0));
 
535
      break;
 
536
 
 
537
    case SYNC_SPDIF:
 
538
      tmp |= 0x10;
 
539
      OUTB (devc->osdev, tmp, devc->mt_base + 0x01);
 
540
      WriteGPIObit (devc, WCLOCK_ENABLE, 0);
 
541
      write_d1010lt_spdif_reg (devc, 4,
 
542
                               read_d1010lt_spdif_reg (devc, 4) | BIT0);
 
543
      break;
 
544
 
 
545
    case SYNC_WCLOCK:
 
546
      tmp |= 0x10;
 
547
      OUTB (devc->osdev, tmp, devc->mt_base + 0x01);
 
548
      WriteGPIObit (devc, WCLOCK_ENABLE, 1);
 
549
      write_d1010lt_spdif_reg (devc, 4,
 
550
                               read_d1010lt_spdif_reg (devc, 4) & (~BIT0));
 
551
      if (devc->model_data->svid == 0xd63014ff)
 
552
        {
 
553
          /*
 
554
           * 1010 rev E only
 
555
           * don't aks me why, but it seems to work
 
556
           */
 
557
          WriteGPIObit (devc, 6, 0);
 
558
          WriteGPIObit (devc, WCLOCK_ENABLE, 1);
 
559
        }
 
560
      break;
 
561
    }
 
562
}
 
563
 
 
564
static int
 
565
d1010lt_get_locked_status (envy24_devc * devc)
 
566
{
 
567
  /* TODO */
 
568
  return 1;
 
569
}
 
570
 
 
571
envy24_auxdrv_t d1010lt_auxdrv = {
 
572
  d1010lt_card_init,
 
573
  d1010lt_mix_init,
 
574
  init_cs8427_spdif,
 
575
  write_cs8427_spdif,
 
576
  cs8427_spdif_ioctl,
 
577
  read_d1010lt_spdif_reg,
 
578
  write_d1010lt_spdif_reg,
 
579
  set_d1010lt_speed,
 
580
  d1010lt_get_locked_status,
 
581
  cs8427_spdif_mixer_init
 
582
};