Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
6bcdbd55
Commit
6bcdbd55
authored
Dec 20, 2008
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/ca0106-resume' into topic/ca0106
parents
6a843641
72077aa3
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
456 additions
and
269 deletions
+456
-269
sound/pci/ca0106/ca0106.h
sound/pci/ca0106/ca0106.h
+14
-1
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_main.c
+312
-216
sound/pci/ca0106/ca0106_mixer.c
sound/pci/ca0106/ca0106_mixer.c
+130
-52
No files found.
sound/pci/ca0106/ca0106.h
View file @
6bcdbd55
...
...
@@ -690,7 +690,7 @@ struct snd_ca0106 {
spinlock_t
emu_lock
;
struct
snd_ac97
*
ac97
;
struct
snd_pcm
*
pcm
;
struct
snd_pcm
*
pcm
[
4
]
;
struct
snd_ca0106_channel
playback_channels
[
4
];
struct
snd_ca0106_channel
capture_channels
[
4
];
...
...
@@ -707,6 +707,11 @@ struct snd_ca0106 {
struct
snd_ca_midi
midi2
;
u16
spi_dac_reg
[
16
];
#ifdef CONFIG_PM
#define NUM_SAVED_VOLUMES 9
unsigned
int
saved_vol
[
NUM_SAVED_VOLUMES
];
#endif
};
int
snd_ca0106_mixer
(
struct
snd_ca0106
*
emu
);
...
...
@@ -725,3 +730,11 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value);
int
snd_ca0106_spi_write
(
struct
snd_ca0106
*
emu
,
unsigned
int
data
);
#ifdef CONFIG_PM
void
snd_ca0106_mixer_suspend
(
struct
snd_ca0106
*
chip
);
void
snd_ca0106_mixer_resume
(
struct
snd_ca0106
*
chip
);
#else
#define snd_ca0106_mixer_suspend(chip) do { } while (0)
#define snd_ca0106_mixer_resume(chip) do { } while (0)
#endif
sound/pci/ca0106/ca0106_main.c
View file @
6bcdbd55
...
...
@@ -853,15 +853,18 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
struct
snd_pcm_substream
*
s
;
u32
basic
=
0
;
u32
extended
=
0
;
int
running
=
0
;
u32
bits
;
int
running
=
0
;
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
running
=
1
;
case
SNDRV_PCM_TRIGGER_RESUME
:
running
=
1
;
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
case
SNDRV_PCM_TRIGGER_SUSPEND
:
default:
running
=
0
;
running
=
0
;
break
;
}
snd_pcm_group_for_each_entry
(
s
,
substream
)
{
...
...
@@ -871,22 +874,32 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
runtime
=
s
->
runtime
;
epcm
=
runtime
->
private_data
;
channel
=
epcm
->
channel_id
;
/
/snd_printk("channel=%d\n",channel);
/
* snd_printk("channel=%d\n",channel); */
epcm
->
running
=
running
;
basic
|=
(
0x1
<<
channel
);
extended
|=
(
0x10
<<
channel
);
basic
|=
(
0x1
<<
channel
);
extended
|=
(
0x10
<<
channel
);
snd_pcm_trigger_done
(
s
,
substream
);
}
/
/snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
/
* snd_printk("basic=0x%x, extended=0x%x\n",basic, extended); */
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
snd_ca0106_ptr_write
(
emu
,
EXTENDED_INT_MASK
,
0
,
snd_ca0106_ptr_read
(
emu
,
EXTENDED_INT_MASK
,
0
)
|
(
extended
));
snd_ca0106_ptr_write
(
emu
,
BASIC_INTERRUPT
,
0
,
snd_ca0106_ptr_read
(
emu
,
BASIC_INTERRUPT
,
0
)
|
(
basic
));
case
SNDRV_PCM_TRIGGER_RESUME
:
bits
=
snd_ca0106_ptr_read
(
emu
,
EXTENDED_INT_MASK
,
0
);
bits
|=
extended
;
snd_ca0106_ptr_write
(
emu
,
EXTENDED_INT_MASK
,
0
,
bits
);
bits
=
snd_ca0106_ptr_read
(
emu
,
BASIC_INTERRUPT
,
0
);
bits
|=
basic
;
snd_ca0106_ptr_write
(
emu
,
BASIC_INTERRUPT
,
0
,
bits
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
snd_ca0106_ptr_write
(
emu
,
BASIC_INTERRUPT
,
0
,
snd_ca0106_ptr_read
(
emu
,
BASIC_INTERRUPT
,
0
)
&
~
(
basic
));
snd_ca0106_ptr_write
(
emu
,
EXTENDED_INT_MASK
,
0
,
snd_ca0106_ptr_read
(
emu
,
EXTENDED_INT_MASK
,
0
)
&
~
(
extended
));
case
SNDRV_PCM_TRIGGER_SUSPEND
:
bits
=
snd_ca0106_ptr_read
(
emu
,
BASIC_INTERRUPT
,
0
);
bits
&=
~
basic
;
snd_ca0106_ptr_write
(
emu
,
BASIC_INTERRUPT
,
0
,
bits
);
bits
=
snd_ca0106_ptr_read
(
emu
,
EXTENDED_INT_MASK
,
0
);
bits
&=
~
extended
;
snd_ca0106_ptr_write
(
emu
,
EXTENDED_INT_MASK
,
0
,
bits
);
break
;
default:
result
=
-
EINVAL
;
...
...
@@ -1109,21 +1122,13 @@ static int snd_ca0106_ac97(struct snd_ca0106 *chip)
return
snd_ac97_mixer
(
pbus
,
&
ac97
,
&
chip
->
ac97
);
}
static
void
ca0106_stop_chip
(
struct
snd_ca0106
*
chip
);
static
int
snd_ca0106_free
(
struct
snd_ca0106
*
chip
)
{
if
(
chip
->
res_port
!=
NULL
)
{
/* avoid access to already used hardware */
// disable interrupts
snd_ca0106_ptr_write
(
chip
,
BASIC_INTERRUPT
,
0
,
0
);
outl
(
0
,
chip
->
port
+
INTE
);
snd_ca0106_ptr_write
(
chip
,
EXTENDED_INT_MASK
,
0
,
0
);
udelay
(
1000
);
// disable audio
//outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
outl
(
0
,
chip
->
port
+
HCFG
);
/* FIXME: We need to stop and DMA transfers here.
* But as I am not sure how yet, we cannot from the dma pages.
* So we can fix: snd-malloc: Memory leak? pages not freed = 8
*/
if
(
chip
->
res_port
!=
NULL
)
{
/* avoid access to already used hardware */
ca0106_stop_chip
(
chip
);
}
if
(
chip
->
irq
>=
0
)
free_irq
(
chip
->
irq
,
chip
);
...
...
@@ -1209,15 +1214,14 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
return
IRQ_HANDLED
;
}
static
int
__devinit
snd_ca0106_pcm
(
struct
snd_ca0106
*
emu
,
int
device
,
struct
snd_pcm
**
rpcm
)
static
int
__devinit
snd_ca0106_pcm
(
struct
snd_ca0106
*
emu
,
int
device
)
{
struct
snd_pcm
*
pcm
;
struct
snd_pcm_substream
*
substream
;
int
err
;
if
(
rpcm
)
*
rpcm
=
NULL
;
if
((
err
=
snd_pcm_new
(
emu
->
card
,
"ca0106"
,
device
,
1
,
1
,
&
pcm
))
<
0
)
err
=
snd_pcm_new
(
emu
->
card
,
"ca0106"
,
device
,
1
,
1
,
&
pcm
);
if
(
err
<
0
)
return
err
;
pcm
->
private_data
=
emu
;
...
...
@@ -1244,7 +1248,6 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s
pcm
->
info_flags
=
0
;
pcm
->
dev_subclass
=
SNDRV_PCM_SUBCLASS_GENERIC_MIX
;
strcpy
(
pcm
->
name
,
"CA0106"
);
emu
->
pcm
=
pcm
;
for
(
substream
=
pcm
->
streams
[
SNDRV_PCM_STREAM_PLAYBACK
].
substream
;
substream
;
...
...
@@ -1266,8 +1269,7 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s
return
err
;
}
if
(
rpcm
)
*
rpcm
=
pcm
;
emu
->
pcm
[
device
]
=
pcm
;
return
0
;
}
...
...
@@ -1307,89 +1309,10 @@ static unsigned int i2c_adc_init[][2] = {
{
0x15
,
ADC_MUX_LINEIN
},
/* ADC Mixer control */
};
static
int
__devinit
snd_ca0106_create
(
int
dev
,
struct
snd_card
*
card
,
struct
pci_dev
*
pci
,
struct
snd_ca0106
**
rchip
)
static
void
ca0106_init_chip
(
struct
snd_ca0106
*
chip
,
int
resume
)
{
struct
snd_ca0106
*
chip
;
struct
snd_ca0106_details
*
c
;
int
err
;
int
ch
;
static
struct
snd_device_ops
ops
=
{
.
dev_free
=
snd_ca0106_dev_free
,
};
*
rchip
=
NULL
;
if
((
err
=
pci_enable_device
(
pci
))
<
0
)
return
err
;
if
(
pci_set_dma_mask
(
pci
,
DMA_32BIT_MASK
)
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_32BIT_MASK
)
<
0
)
{
printk
(
KERN_ERR
"error to set 32bit mask DMA
\n
"
);
pci_disable_device
(
pci
);
return
-
ENXIO
;
}
chip
=
kzalloc
(
sizeof
(
*
chip
),
GFP_KERNEL
);
if
(
chip
==
NULL
)
{
pci_disable_device
(
pci
);
return
-
ENOMEM
;
}
chip
->
card
=
card
;
chip
->
pci
=
pci
;
chip
->
irq
=
-
1
;
spin_lock_init
(
&
chip
->
emu_lock
);
chip
->
port
=
pci_resource_start
(
pci
,
0
);
if
((
chip
->
res_port
=
request_region
(
chip
->
port
,
0x20
,
"snd_ca0106"
))
==
NULL
)
{
snd_ca0106_free
(
chip
);
printk
(
KERN_ERR
"cannot allocate the port
\n
"
);
return
-
EBUSY
;
}
if
(
request_irq
(
pci
->
irq
,
snd_ca0106_interrupt
,
IRQF_SHARED
,
"snd_ca0106"
,
chip
))
{
snd_ca0106_free
(
chip
);
printk
(
KERN_ERR
"cannot grab irq
\n
"
);
return
-
EBUSY
;
}
chip
->
irq
=
pci
->
irq
;
/* This stores the periods table. */
if
(
snd_dma_alloc_pages
(
SNDRV_DMA_TYPE_DEV
,
snd_dma_pci_data
(
pci
),
1024
,
&
chip
->
buffer
)
<
0
)
{
snd_ca0106_free
(
chip
);
return
-
ENOMEM
;
}
pci_set_master
(
pci
);
/* read serial */
pci_read_config_dword
(
pci
,
PCI_SUBSYSTEM_VENDOR_ID
,
&
chip
->
serial
);
pci_read_config_word
(
pci
,
PCI_SUBSYSTEM_ID
,
&
chip
->
model
);
#if 1
printk
(
KERN_INFO
"snd-ca0106: Model %04x Rev %08x Serial %08x
\n
"
,
chip
->
model
,
pci
->
revision
,
chip
->
serial
);
#endif
strcpy
(
card
->
driver
,
"CA0106"
);
strcpy
(
card
->
shortname
,
"CA0106"
);
for
(
c
=
ca0106_chip_details
;
c
->
serial
;
c
++
)
{
if
(
subsystem
[
dev
])
{
if
(
c
->
serial
==
subsystem
[
dev
])
break
;
}
else
if
(
c
->
serial
==
chip
->
serial
)
break
;
}
chip
->
details
=
c
;
if
(
subsystem
[
dev
])
{
printk
(
KERN_INFO
"snd-ca0106: Sound card name=%s, subsystem=0x%x. Forced to subsystem=0x%x
\n
"
,
c
->
name
,
chip
->
serial
,
subsystem
[
dev
]);
}
sprintf
(
card
->
longname
,
"%s at 0x%lx irq %i"
,
c
->
name
,
chip
->
port
,
chip
->
irq
);
unsigned
int
def_bits
;
outl
(
0
,
chip
->
port
+
INTE
);
...
...
@@ -1407,31 +1330,22 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
* AN = 0 (Audio data)
* P = 0 (Consumer)
*/
snd_ca0106_ptr_write
(
chip
,
SPCS0
,
0
,
chip
->
spdif_bits
[
0
]
=
SPCS_CLKACCY_1000PPM
|
SPCS_SAMPLERATE_48
|
SPCS_CHANNELNUM_LEFT
|
SPCS_SOURCENUM_UNSPEC
|
SPCS_GENERATIONSTATUS
|
0x00001200
|
0x00000000
|
SPCS_EMPHASIS_NONE
|
SPCS_COPYRIGHT
);
def_bits
=
SPCS_CLKACCY_1000PPM
|
SPCS_SAMPLERATE_48
|
SPCS_CHANNELNUM_LEFT
|
SPCS_SOURCENUM_UNSPEC
|
SPCS_GENERATIONSTATUS
|
0x00001200
|
0x00000000
|
SPCS_EMPHASIS_NONE
|
SPCS_COPYRIGHT
;
if
(
!
resume
)
{
chip
->
spdif_bits
[
0
]
=
def_bits
;
chip
->
spdif_bits
[
1
]
=
def_bits
;
chip
->
spdif_bits
[
2
]
=
def_bits
;
chip
->
spdif_bits
[
3
]
=
def_bits
;
}
/* Only SPCS1 has been tested */
snd_ca0106_ptr_write
(
chip
,
SPCS1
,
0
,
chip
->
spdif_bits
[
1
]
=
SPCS_CLKACCY_1000PPM
|
SPCS_SAMPLERATE_48
|
SPCS_CHANNELNUM_LEFT
|
SPCS_SOURCENUM_UNSPEC
|
SPCS_GENERATIONSTATUS
|
0x00001200
|
0x00000000
|
SPCS_EMPHASIS_NONE
|
SPCS_COPYRIGHT
);
snd_ca0106_ptr_write
(
chip
,
SPCS2
,
0
,
chip
->
spdif_bits
[
2
]
=
SPCS_CLKACCY_1000PPM
|
SPCS_SAMPLERATE_48
|
SPCS_CHANNELNUM_LEFT
|
SPCS_SOURCENUM_UNSPEC
|
SPCS_GENERATIONSTATUS
|
0x00001200
|
0x00000000
|
SPCS_EMPHASIS_NONE
|
SPCS_COPYRIGHT
);
snd_ca0106_ptr_write
(
chip
,
SPCS3
,
0
,
chip
->
spdif_bits
[
3
]
=
SPCS_CLKACCY_1000PPM
|
SPCS_SAMPLERATE_48
|
SPCS_CHANNELNUM_LEFT
|
SPCS_SOURCENUM_UNSPEC
|
SPCS_GENERATIONSTATUS
|
0x00001200
|
0x00000000
|
SPCS_EMPHASIS_NONE
|
SPCS_COPYRIGHT
);
snd_ca0106_ptr_write
(
chip
,
SPCS1
,
0
,
chip
->
spdif_bits
[
1
]);
snd_ca0106_ptr_write
(
chip
,
SPCS0
,
0
,
chip
->
spdif_bits
[
0
]);
snd_ca0106_ptr_write
(
chip
,
SPCS2
,
0
,
chip
->
spdif_bits
[
2
]);
snd_ca0106_ptr_write
(
chip
,
SPCS3
,
0
,
chip
->
spdif_bits
[
3
]);
snd_ca0106_ptr_write
(
chip
,
PLAYBACK_MUTE
,
0
,
0x00fc0000
);
snd_ca0106_ptr_write
(
chip
,
CAPTURE_MUTE
,
0
,
0x00fc0000
);
...
...
@@ -1439,92 +1353,124 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
/* Write 0x8000 to AC97_REC_GAIN to mute it. */
outb
(
AC97_REC_GAIN
,
chip
->
port
+
AC97ADDRESS
);
outw
(
0x8000
,
chip
->
port
+
AC97DATA
);
#if 0
#if 0
/* FIXME: what are these? */
snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);
snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);
snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);
snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);
#endif
//snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
/* OSS drivers set this. */
/* snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); */
/* Analog or Digital output */
snd_ca0106_ptr_write
(
chip
,
SPDIF_SELECT1
,
0
,
0xf
);
snd_ca0106_ptr_write
(
chip
,
SPDIF_SELECT2
,
0
,
0x000f0000
);
/* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */
/* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers.
* Use 0x000f0000 for surround71
*/
snd_ca0106_ptr_write
(
chip
,
SPDIF_SELECT2
,
0
,
0x000f0000
);
chip
->
spdif_enable
=
0
;
/* Set digital SPDIF output off */
//snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
//snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
/*snd_ca0106_ptr_write(chip, 0x45, 0, 0);*/
/* Analogue out */
/*snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00);*/
/* Digital out */
/* goes to 0x40c80000 when doing SPDIF IN/OUT */
snd_ca0106_ptr_write
(
chip
,
CAPTURE_CONTROL
,
0
,
0x40c81000
);
/* (Mute) CAPTURE feedback into PLAYBACK volume.
* Only lower 16 bits matter.
*/
snd_ca0106_ptr_write
(
chip
,
CAPTURE_CONTROL
,
1
,
0xffffffff
);
/* SPDIF IN Volume */
snd_ca0106_ptr_write
(
chip
,
CAPTURE_CONTROL
,
2
,
0x30300000
);
/* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
snd_ca0106_ptr_write
(
chip
,
CAPTURE_CONTROL
,
3
,
0x00700000
);
snd_ca0106_ptr_write
(
chip
,
CAPTURE_CONTROL
,
0
,
0x40c81000
);
/* goes to 0x40c80000 when doing SPDIF IN/OUT */
snd_ca0106_ptr_write
(
chip
,
CAPTURE_CONTROL
,
1
,
0xffffffff
);
/* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */
snd_ca0106_ptr_write
(
chip
,
CAPTURE_CONTROL
,
2
,
0x30300000
);
/* SPDIF IN Volume */
snd_ca0106_ptr_write
(
chip
,
CAPTURE_CONTROL
,
3
,
0x00700000
);
/* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
snd_ca0106_ptr_write
(
chip
,
PLAYBACK_ROUTING1
,
0
,
0x32765410
);
snd_ca0106_ptr_write
(
chip
,
PLAYBACK_ROUTING2
,
0
,
0x76767676
);
snd_ca0106_ptr_write
(
chip
,
CAPTURE_ROUTING1
,
0
,
0x32765410
);
snd_ca0106_ptr_write
(
chip
,
CAPTURE_ROUTING2
,
0
,
0x76767676
);
for
(
ch
=
0
;
ch
<
4
;
ch
++
)
{
snd_ca0106_ptr_write
(
chip
,
CAPTURE_VOLUME1
,
ch
,
0x30303030
);
/* Only high 16 bits matter */
for
(
ch
=
0
;
ch
<
4
;
ch
++
)
{
/* Only high 16 bits matter */
snd_ca0106_ptr_write
(
chip
,
CAPTURE_VOLUME1
,
ch
,
0x30303030
);
snd_ca0106_ptr_write
(
chip
,
CAPTURE_VOLUME2
,
ch
,
0x30303030
);
//snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */
//snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */
snd_ca0106_ptr_write
(
chip
,
PLAYBACK_VOLUME1
,
ch
,
0xffffffff
);
/* Mute */
snd_ca0106_ptr_write
(
chip
,
PLAYBACK_VOLUME2
,
ch
,
0xffffffff
);
/* Mute */
#if 0 /* Mute */
snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040);
snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040);
snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff);
snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff);
#endif
}
if
(
chip
->
details
->
i2c_adc
==
1
)
{
/* Select MIC, Line in, TAD in, AUX in */
snd_ca0106_ptr_write
(
chip
,
CAPTURE_SOURCE
,
0x0
,
0x333300e4
);
/* Default to CAPTURE_SOURCE to i2s in */
chip
->
capture_source
=
3
;
if
(
!
resume
)
chip
->
capture_source
=
3
;
}
else
if
(
chip
->
details
->
ac97
==
1
)
{
/* Default to AC97 in */
snd_ca0106_ptr_write
(
chip
,
CAPTURE_SOURCE
,
0x0
,
0x444400e4
);
/* Default to CAPTURE_SOURCE to AC97 in */
chip
->
capture_source
=
4
;
if
(
!
resume
)
chip
->
capture_source
=
4
;
}
else
{
/* Select MIC, Line in, TAD in, AUX in */
snd_ca0106_ptr_write
(
chip
,
CAPTURE_SOURCE
,
0x0
,
0x333300e4
);
/* Default to Set CAPTURE_SOURCE to i2s in */
chip
->
capture_source
=
3
;
if
(
!
resume
)
chip
->
capture_source
=
3
;
}
if
(
chip
->
details
->
gpio_type
==
2
)
{
/* The SB0438 use GPIO differently. */
/* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
if
(
chip
->
details
->
gpio_type
==
2
)
{
/* The SB0438 use GPIO differently. */
/* FIXME: Still need to find out what the other GPIO bits do.
* E.g. For digital spdif out.
*/
outl
(
0x0
,
chip
->
port
+
GPIO
);
/
/outl(0x00f0e000, chip->port+GPIO);
/* Analog */
/
* outl(0x00f0e000, chip->port+GPIO); */
/* Analog */
outl
(
0x005f5301
,
chip
->
port
+
GPIO
);
/* Analog */
}
else
if
(
chip
->
details
->
gpio_type
==
1
)
{
/* The SB0410 and SB0413 use GPIO differently. */
/* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
}
else
if
(
chip
->
details
->
gpio_type
==
1
)
{
/* The SB0410 and SB0413 use GPIO differently. */
/* FIXME: Still need to find out what the other GPIO bits do.
* E.g. For digital spdif out.
*/
outl
(
0x0
,
chip
->
port
+
GPIO
);
/
/outl(0x00f0e000, chip->port+GPIO);
/* Analog */
/
* outl(0x00f0e000, chip->port+GPIO); */
/* Analog */
outl
(
0x005f5301
,
chip
->
port
+
GPIO
);
/* Analog */
}
else
{
outl
(
0x0
,
chip
->
port
+
GPIO
);
outl
(
0x005f03a3
,
chip
->
port
+
GPIO
);
/* Analog */
/
/outl(0x005f02a2, chip->port+GPIO);
/* SPDIF */
/
* outl(0x005f02a2, chip->port+GPIO); */
/* SPDIF */
}
snd_ca0106_intr_enable
(
chip
,
0x105
);
/* Win2000 uses 0x1e0 */
//outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
//outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
//outl(0x00000009, chip->port+HCFG);
outl
(
HCFG_AC97
|
HCFG_AUDIOENABLE
,
chip
->
port
+
HCFG
);
/* AC97 2.0, Enable outputs. */
/* outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); */
/* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
/* outl(0x00001409, chip->port+HCFG); */
/* outl(0x00000009, chip->port+HCFG); */
/* AC97 2.0, Enable outputs. */
outl
(
HCFG_AC97
|
HCFG_AUDIOENABLE
,
chip
->
port
+
HCFG
);
if
(
chip
->
details
->
i2c_adc
==
1
)
{
/* The SB0410 and SB0413 use I2C to control ADC. */
if
(
chip
->
details
->
i2c_adc
==
1
)
{
/* The SB0410 and SB0413 use I2C to control ADC. */
int
size
,
n
;
size
=
ARRAY_SIZE
(
i2c_adc_init
);
//snd_printk("I2C:array size=0x%x\n", size);
for
(
n
=
0
;
n
<
size
;
n
++
)
{
snd_ca0106_i2c_write
(
chip
,
i2c_adc_init
[
n
][
0
],
i2c_adc_init
[
n
][
1
]);
}
for
(
n
=
0
;
n
<
4
;
n
++
)
{
chip
->
i2c_capture_volume
[
n
][
0
]
=
0xcf
;
chip
->
i2c_capture_volume
[
n
][
1
]
=
0xcf
;
/* snd_printk("I2C:array size=0x%x\n", size); */
for
(
n
=
0
;
n
<
size
;
n
++
)
snd_ca0106_i2c_write
(
chip
,
i2c_adc_init
[
n
][
0
],
i2c_adc_init
[
n
][
1
]);
for
(
n
=
0
;
n
<
4
;
n
++
)
{
chip
->
i2c_capture_volume
[
n
][
0
]
=
0xcf
;
chip
->
i2c_capture_volume
[
n
][
1
]
=
0xcf
;
}
chip
->
i2c_capture_source
=
2
;
/* Line in */
//snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
chip
->
i2c_capture_source
=
2
;
/* Line in */
/* Enable Line-in capture. MIC in currently untested. */
/* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */
}
if
(
chip
->
details
->
spi_dac
==
1
)
{
/* The SB0570 use SPI to control DAC. */
if
(
chip
->
details
->
spi_dac
==
1
)
{
/* The SB0570 use SPI to control DAC. */
int
size
,
n
;
size
=
ARRAY_SIZE
(
spi_dac_init
);
...
...
@@ -1536,9 +1482,112 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
chip
->
spi_dac_reg
[
reg
]
=
spi_dac_init
[
n
];
}
}
}
static
void
ca0106_stop_chip
(
struct
snd_ca0106
*
chip
)
{
/* disable interrupts */
snd_ca0106_ptr_write
(
chip
,
BASIC_INTERRUPT
,
0
,
0
);
outl
(
0
,
chip
->
port
+
INTE
);
snd_ca0106_ptr_write
(
chip
,
EXTENDED_INT_MASK
,
0
,
0
);
udelay
(
1000
);
/* disable audio */
/* outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); */
outl
(
0
,
chip
->
port
+
HCFG
);
/* FIXME: We need to stop and DMA transfers here.
* But as I am not sure how yet, we cannot from the dma pages.
* So we can fix: snd-malloc: Memory leak? pages not freed = 8
*/
}
static
int
__devinit
snd_ca0106_create
(
int
dev
,
struct
snd_card
*
card
,
struct
pci_dev
*
pci
,
struct
snd_ca0106
**
rchip
)
{
struct
snd_ca0106
*
chip
;
struct
snd_ca0106_details
*
c
;
int
err
;
static
struct
snd_device_ops
ops
=
{
.
dev_free
=
snd_ca0106_dev_free
,
};
*
rchip
=
NULL
;
if
((
err
=
snd_device_new
(
card
,
SNDRV_DEV_LOWLEVEL
,
chip
,
&
ops
))
<
0
)
{
err
=
pci_enable_device
(
pci
);
if
(
err
<
0
)
return
err
;
if
(
pci_set_dma_mask
(
pci
,
DMA_32BIT_MASK
)
<
0
||
pci_set_consistent_dma_mask
(
pci
,
DMA_32BIT_MASK
)
<
0
)
{
printk
(
KERN_ERR
"error to set 32bit mask DMA
\n
"
);
pci_disable_device
(
pci
);
return
-
ENXIO
;
}
chip
=
kzalloc
(
sizeof
(
*
chip
),
GFP_KERNEL
);
if
(
chip
==
NULL
)
{
pci_disable_device
(
pci
);
return
-
ENOMEM
;
}
chip
->
card
=
card
;
chip
->
pci
=
pci
;
chip
->
irq
=
-
1
;
spin_lock_init
(
&
chip
->
emu_lock
);
chip
->
port
=
pci_resource_start
(
pci
,
0
);
chip
->
res_port
=
request_region
(
chip
->
port
,
0x20
,
"snd_ca0106"
);
if
(
!
chip
->
res_port
)
{
snd_ca0106_free
(
chip
);
printk
(
KERN_ERR
"cannot allocate the port
\n
"
);
return
-
EBUSY
;
}
if
(
request_irq
(
pci
->
irq
,
snd_ca0106_interrupt
,
IRQF_SHARED
,
"snd_ca0106"
,
chip
))
{
snd_ca0106_free
(
chip
);
printk
(
KERN_ERR
"cannot grab irq
\n
"
);
return
-
EBUSY
;
}
chip
->
irq
=
pci
->
irq
;
/* This stores the periods table. */
if
(
snd_dma_alloc_pages
(
SNDRV_DMA_TYPE_DEV
,
snd_dma_pci_data
(
pci
),
1024
,
&
chip
->
buffer
)
<
0
)
{
snd_ca0106_free
(
chip
);
return
-
ENOMEM
;
}
pci_set_master
(
pci
);
/* read serial */
pci_read_config_dword
(
pci
,
PCI_SUBSYSTEM_VENDOR_ID
,
&
chip
->
serial
);
pci_read_config_word
(
pci
,
PCI_SUBSYSTEM_ID
,
&
chip
->
model
);
printk
(
KERN_INFO
"snd-ca0106: Model %04x Rev %08x Serial %08x
\n
"
,
chip
->
model
,
pci
->
revision
,
chip
->
serial
);
strcpy
(
card
->
driver
,
"CA0106"
);
strcpy
(
card
->
shortname
,
"CA0106"
);
for
(
c
=
ca0106_chip_details
;
c
->
serial
;
c
++
)
{
if
(
subsystem
[
dev
])
{
if
(
c
->
serial
==
subsystem
[
dev
])
break
;
}
else
if
(
c
->
serial
==
chip
->
serial
)
break
;
}
chip
->
details
=
c
;
if
(
subsystem
[
dev
])
{
printk
(
KERN_INFO
"snd-ca0106: Sound card name=%s, "
"subsystem=0x%x. Forced to subsystem=0x%x
\n
"
,
c
->
name
,
chip
->
serial
,
subsystem
[
dev
]);
}
sprintf
(
card
->
longname
,
"%s at 0x%lx irq %i"
,
c
->
name
,
chip
->
port
,
chip
->
irq
);
ca0106_init_chip
(
chip
,
0
);
err
=
snd_device_new
(
card
,
SNDRV_DEV_LOWLEVEL
,
chip
,
&
ops
);
if
(
err
<
0
)
{
snd_ca0106_free
(
chip
);
return
err
;
}
...
...
@@ -1635,7 +1684,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
static
int
dev
;
struct
snd_card
*
card
;
struct
snd_ca0106
*
chip
;
int
err
;
int
i
,
err
;
if
(
dev
>=
SNDRV_CARDS
)
return
-
ENODEV
;
...
...
@@ -1648,44 +1697,31 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
if
(
card
==
NULL
)
return
-
ENOMEM
;
if
((
err
=
snd_ca0106_create
(
dev
,
card
,
pci
,
&
chip
))
<
0
)
{
snd_card_free
(
card
);
return
er
r
;
}
err
=
snd_ca0106_create
(
dev
,
card
,
pci
,
&
chip
);
if
(
err
<
0
)
goto
erro
r
;
card
->
private_data
=
chip
;
if
((
err
=
snd_ca0106_pcm
(
chip
,
0
,
NULL
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
if
((
err
=
snd_ca0106_pcm
(
chip
,
1
,
NULL
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
if
((
err
=
snd_ca0106_pcm
(
chip
,
2
,
NULL
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
if
((
err
=
snd_ca0106_pcm
(
chip
,
3
,
NULL
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
if
(
chip
->
details
->
ac97
==
1
)
{
/* The SB0410 and SB0413 do not have an AC97 chip. */
if
((
err
=
snd_ca0106_ac97
(
chip
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
for
(
i
=
0
;
i
<
4
;
i
++
)
{
err
=
snd_ca0106_pcm
(
chip
,
i
);
if
(
err
<
0
)
goto
error
;
}
if
((
err
=
snd_ca0106_mixer
(
chip
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
if
(
chip
->
details
->
ac97
==
1
)
{
/* The SB0410 and SB0413 do not have an AC97 chip. */
err
=
snd_ca0106_ac97
(
chip
);
if
(
err
<
0
)
goto
error
;
}
err
=
snd_ca0106_mixer
(
chip
);
if
(
err
<
0
)
goto
error
;
snd_printdd
(
"ca0106: probe for MIDI channel A ..."
);
if
((
err
=
snd_ca0106_midi
(
chip
,
CA0106_MIDI_CHAN_A
))
<
0
)
{
snd_card_free
(
card
);
snd_printdd
(
" failed, err=0x%x
\n
"
,
err
);
return
err
;
}
err
=
snd_ca0106_midi
(
chip
,
CA0106_MIDI_CHAN_A
);
if
(
err
<
0
)
goto
error
;
snd_printdd
(
" done.
\n
"
);
#ifdef CONFIG_PROC_FS
...
...
@@ -1694,14 +1730,17 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
snd_card_set_dev
(
card
,
&
pci
->
dev
);
if
((
err
=
snd_card_register
(
card
))
<
0
)
{
snd_card_free
(
card
);
return
err
;
}
err
=
snd_card_register
(
card
);
if
(
err
<
0
)
goto
error
;
pci_set_drvdata
(
pci
,
card
);
dev
++
;
return
0
;
error:
snd_card_free
(
card
);
return
err
;
}
static
void
__devexit
snd_ca0106_remove
(
struct
pci_dev
*
pci
)
...
...
@@ -1710,6 +1749,59 @@ static void __devexit snd_ca0106_remove(struct pci_dev *pci)
pci_set_drvdata
(
pci
,
NULL
);
}
#ifdef CONFIG_PM
static
int
snd_ca0106_suspend
(
struct
pci_dev
*
pci
,
pm_message_t
state
)
{
struct
snd_card
*
card
=
pci_get_drvdata
(
pci
);
struct
snd_ca0106
*
chip
=
card
->
private_data
;
int
i
;
snd_power_change_state
(
card
,
SNDRV_CTL_POWER_D3hot
);
for
(
i
=
0
;
i
<
4
;
i
++
)
snd_pcm_suspend_all
(
chip
->
pcm
[
i
]);
if
(
chip
->
details
->
ac97
)
snd_ac97_suspend
(
chip
->
ac97
);
snd_ca0106_mixer_suspend
(
chip
);
ca0106_stop_chip
(
chip
);
pci_disable_device
(
pci
);
pci_save_state
(
pci
);
pci_set_power_state
(
pci
,
pci_choose_state
(
pci
,
state
));
return
0
;
}
static
int
snd_ca0106_resume
(
struct
pci_dev
*
pci
)
{
struct
snd_card
*
card
=
pci_get_drvdata
(
pci
);
struct
snd_ca0106
*
chip
=
card
->
private_data
;
int
i
;
pci_set_power_state
(
pci
,
PCI_D0
);
pci_restore_state
(
pci
);
if
(
pci_enable_device
(
pci
)
<
0
)
{
snd_card_disconnect
(
card
);
return
-
EIO
;
}
pci_set_master
(
pci
);
ca0106_init_chip
(
chip
,
1
);
if
(
chip
->
details
->
ac97
)
snd_ac97_resume
(
chip
->
ac97
);
snd_ca0106_mixer_resume
(
chip
);
if
(
chip
->
details
->
spi_dac
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
chip
->
spi_dac_reg
);
i
++
)
snd_ca0106_spi_write
(
chip
,
chip
->
spi_dac_reg
[
i
]);
}
snd_power_change_state
(
card
,
SNDRV_CTL_POWER_D0
);
return
0
;
}
#endif
// PCI IDs
static
struct
pci_device_id
snd_ca0106_ids
[]
=
{
{
0x1102
,
0x0007
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
/* Audigy LS or Live 24bit */
...
...
@@ -1723,6 +1815,10 @@ static struct pci_driver driver = {
.
id_table
=
snd_ca0106_ids
,
.
probe
=
snd_ca0106_probe
,
.
remove
=
__devexit_p
(
snd_ca0106_remove
),
#ifdef CONFIG_PM
.
suspend
=
snd_ca0106_suspend
,
.
resume
=
snd_ca0106_resume
,
#endif
};
// initialization of the module
...
...
sound/pci/ca0106/ca0106_mixer.c
View file @
6bcdbd55
...
...
@@ -75,6 +75,84 @@
#include "ca0106.h"
static
void
ca0106_spdif_enable
(
struct
snd_ca0106
*
emu
)
{
unsigned
int
val
;
if
(
emu
->
spdif_enable
)
{
/* Digital */
snd_ca0106_ptr_write
(
emu
,
SPDIF_SELECT1
,
0
,
0xf
);
snd_ca0106_ptr_write
(
emu
,
SPDIF_SELECT2
,
0
,
0x0b000000
);
val
=
snd_ca0106_ptr_read
(
emu
,
CAPTURE_CONTROL
,
0
)
&
~
0x1000
;
snd_ca0106_ptr_write
(
emu
,
CAPTURE_CONTROL
,
0
,
val
);
val
=
inl
(
emu
->
port
+
GPIO
)
&
~
0x101
;
outl
(
val
,
emu
->
port
+
GPIO
);
}
else
{
/* Analog */
snd_ca0106_ptr_write
(
emu
,
SPDIF_SELECT1
,
0
,
0xf
);
snd_ca0106_ptr_write
(
emu
,
SPDIF_SELECT2
,
0
,
0x000f0000
);
val
=
snd_ca0106_ptr_read
(
emu
,
CAPTURE_CONTROL
,
0
)
|
0x1000
;
snd_ca0106_ptr_write
(
emu
,
CAPTURE_CONTROL
,
0
,
val
);
val
=
inl
(
emu
->
port
+
GPIO
)
|
0x101
;
outl
(
val
,
emu
->
port
+
GPIO
);
}
}
static
void
ca0106_set_capture_source
(
struct
snd_ca0106
*
emu
)
{
unsigned
int
val
=
emu
->
capture_source
;
unsigned
int
source
,
mask
;
source
=
(
val
<<
28
)
|
(
val
<<
24
)
|
(
val
<<
20
)
|
(
val
<<
16
);
mask
=
snd_ca0106_ptr_read
(
emu
,
CAPTURE_SOURCE
,
0
)
&
0xffff
;
snd_ca0106_ptr_write
(
emu
,
CAPTURE_SOURCE
,
0
,
source
|
mask
);
}
static
void
ca0106_set_i2c_capture_source
(
struct
snd_ca0106
*
emu
,
unsigned
int
val
,
int
force
)
{
unsigned
int
ngain
,
ogain
;
u32
source
;
snd_ca0106_i2c_write
(
emu
,
ADC_MUX
,
0
);
/* Mute input */
ngain
=
emu
->
i2c_capture_volume
[
val
][
0
];
/* Left */
ogain
=
emu
->
i2c_capture_volume
[
emu
->
i2c_capture_source
][
0
];
/* Left */
if
(
force
||
ngain
!=
ogain
)
snd_ca0106_i2c_write
(
emu
,
ADC_ATTEN_ADCL
,
ngain
&
0xff
);
ngain
=
emu
->
i2c_capture_volume
[
val
][
1
];
/* Right */
ogain
=
emu
->
i2c_capture_volume
[
emu
->
i2c_capture_source
][
1
];
/* Right */
if
(
force
||
ngain
!=
ogain
)
snd_ca0106_i2c_write
(
emu
,
ADC_ATTEN_ADCR
,
ngain
&
0xff
);
source
=
1
<<
val
;
snd_ca0106_i2c_write
(
emu
,
ADC_MUX
,
source
);
/* Set source */
emu
->
i2c_capture_source
=
val
;
}
static
void
ca0106_set_capture_mic_line_in
(
struct
snd_ca0106
*
emu
)
{
u32
tmp
;
if
(
emu
->
capture_mic_line_in
)
{
/* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */
/* Mute input */
tmp
=
inl
(
emu
->
port
+
GPIO
)
&
~
0x400
;
tmp
=
tmp
|
0x400
;
outl
(
tmp
,
emu
->
port
+
GPIO
);
/* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */
}
else
{
/* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */
/* Mute input */
tmp
=
inl
(
emu
->
port
+
GPIO
)
&
~
0x400
;
outl
(
tmp
,
emu
->
port
+
GPIO
);
/* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */
}
}
static
void
ca0106_set_spdif_bits
(
struct
snd_ca0106
*
emu
,
int
idx
)
{
snd_ca0106_ptr_write
(
emu
,
SPCS0
+
idx
,
0
,
emu
->
spdif_bits
[
idx
]);
}
/*
*/
static
const
DECLARE_TLV_DB_SCALE
(
snd_ca0106_db_scale1
,
-
5175
,
25
,
1
);
static
const
DECLARE_TLV_DB_SCALE
(
snd_ca0106_db_scale2
,
-
10350
,
50
,
1
);
...
...
@@ -95,30 +173,12 @@ static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
struct
snd_ca0106
*
emu
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
int
val
;
int
change
=
0
;
u32
mask
;
val
=
!!
ucontrol
->
value
.
integer
.
value
[
0
];
change
=
(
emu
->
spdif_enable
!=
val
);
if
(
change
)
{
emu
->
spdif_enable
=
val
;
if
(
val
)
{
/* Digital */
snd_ca0106_ptr_write
(
emu
,
SPDIF_SELECT1
,
0
,
0xf
);
snd_ca0106_ptr_write
(
emu
,
SPDIF_SELECT2
,
0
,
0x0b000000
);
snd_ca0106_ptr_write
(
emu
,
CAPTURE_CONTROL
,
0
,
snd_ca0106_ptr_read
(
emu
,
CAPTURE_CONTROL
,
0
)
&
~
0x1000
);
mask
=
inl
(
emu
->
port
+
GPIO
)
&
~
0x101
;
outl
(
mask
,
emu
->
port
+
GPIO
);
}
else
{
/* Analog */
snd_ca0106_ptr_write
(
emu
,
SPDIF_SELECT1
,
0
,
0xf
);
snd_ca0106_ptr_write
(
emu
,
SPDIF_SELECT2
,
0
,
0x000f0000
);
snd_ca0106_ptr_write
(
emu
,
CAPTURE_CONTROL
,
0
,
snd_ca0106_ptr_read
(
emu
,
CAPTURE_CONTROL
,
0
)
|
0x1000
);
mask
=
inl
(
emu
->
port
+
GPIO
)
|
0x101
;
outl
(
mask
,
emu
->
port
+
GPIO
);
}
ca0106_spdif_enable
(
emu
);
}
return
change
;
}
...
...
@@ -154,8 +214,6 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
struct
snd_ca0106
*
emu
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
int
val
;
int
change
=
0
;
u32
mask
;
u32
source
;
val
=
ucontrol
->
value
.
enumerated
.
item
[
0
]
;
if
(
val
>=
6
)
...
...
@@ -163,9 +221,7 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
change
=
(
emu
->
capture_source
!=
val
);
if
(
change
)
{
emu
->
capture_source
=
val
;
source
=
(
val
<<
28
)
|
(
val
<<
24
)
|
(
val
<<
20
)
|
(
val
<<
16
);
mask
=
snd_ca0106_ptr_read
(
emu
,
CAPTURE_SOURCE
,
0
)
&
0xffff
;
snd_ca0106_ptr_write
(
emu
,
CAPTURE_SOURCE
,
0
,
source
|
mask
);
ca0106_set_capture_source
(
emu
);
}
return
change
;
}
...
...
@@ -200,9 +256,7 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
{
struct
snd_ca0106
*
emu
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
int
source_id
;
unsigned
int
ngain
,
ogain
;
int
change
=
0
;
u32
source
;
/* If the capture source has changed,
* update the capture volume from the cached value
* for the particular source.
...
...
@@ -212,18 +266,7 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
return
-
EINVAL
;
change
=
(
emu
->
i2c_capture_source
!=
source_id
);
if
(
change
)
{
snd_ca0106_i2c_write
(
emu
,
ADC_MUX
,
0
);
/* Mute input */
ngain
=
emu
->
i2c_capture_volume
[
source_id
][
0
];
/* Left */
ogain
=
emu
->
i2c_capture_volume
[
emu
->
i2c_capture_source
][
0
];
/* Left */
if
(
ngain
!=
ogain
)
snd_ca0106_i2c_write
(
emu
,
ADC_ATTEN_ADCL
,
((
ngain
)
&
0xff
));
ngain
=
emu
->
i2c_capture_volume
[
source_id
][
1
];
/* Left */
ogain
=
emu
->
i2c_capture_volume
[
emu
->
i2c_capture_source
][
1
];
/* Left */
if
(
ngain
!=
ogain
)
snd_ca0106_i2c_write
(
emu
,
ADC_ATTEN_ADCR
,
((
ngain
)
&
0xff
));
source
=
1
<<
source_id
;
snd_ca0106_i2c_write
(
emu
,
ADC_MUX
,
source
);
/* Set source */
emu
->
i2c_capture_source
=
source_id
;
ca0106_set_i2c_capture_source
(
emu
,
source_id
,
0
);
}
return
change
;
}
...
...
@@ -271,7 +314,6 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
struct
snd_ca0106
*
emu
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
int
val
;
int
change
=
0
;
u32
tmp
;
val
=
ucontrol
->
value
.
enumerated
.
item
[
0
]
;
if
(
val
>
1
)
...
...
@@ -279,18 +321,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
change
=
(
emu
->
capture_mic_line_in
!=
val
);
if
(
change
)
{
emu
->
capture_mic_line_in
=
val
;
if
(
val
)
{
//snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
tmp
=
inl
(
emu
->
port
+
GPIO
)
&
~
0x400
;
tmp
=
tmp
|
0x400
;
outl
(
tmp
,
emu
->
port
+
GPIO
);
//snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
}
else
{
//snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
tmp
=
inl
(
emu
->
port
+
GPIO
)
&
~
0x400
;
outl
(
tmp
,
emu
->
port
+
GPIO
);
//snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
}
ca0106_set_capture_mic_line_in
(
emu
);
}
return
change
;
}
...
...
@@ -359,8 +390,8 @@ static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol,
(
ucontrol
->
value
.
iec958
.
status
[
3
]
<<
24
);
change
=
val
!=
emu
->
spdif_bits
[
idx
];
if
(
change
)
{
snd_ca0106_ptr_write
(
emu
,
SPCS0
+
idx
,
0
,
val
);
emu
->
spdif_bits
[
idx
]
=
val
;
ca0106_set_spdif_bits
(
emu
,
idx
);
}
return
change
;
}
...
...
@@ -773,3 +804,50 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
return
0
;
}
#ifdef CONFIG_PM
struct
ca0106_vol_tbl
{
unsigned
int
channel_id
;
unsigned
int
reg
;
};
static
struct
ca0106_vol_tbl
saved_volumes
[
NUM_SAVED_VOLUMES
]
=
{
{
CONTROL_FRONT_CHANNEL
,
PLAYBACK_VOLUME2
},
{
CONTROL_REAR_CHANNEL
,
PLAYBACK_VOLUME2
},
{
CONTROL_CENTER_LFE_CHANNEL
,
PLAYBACK_VOLUME2
},
{
CONTROL_UNKNOWN_CHANNEL
,
PLAYBACK_VOLUME2
},
{
CONTROL_FRONT_CHANNEL
,
PLAYBACK_VOLUME1
},
{
CONTROL_REAR_CHANNEL
,
PLAYBACK_VOLUME1
},
{
CONTROL_CENTER_LFE_CHANNEL
,
PLAYBACK_VOLUME1
},
{
CONTROL_UNKNOWN_CHANNEL
,
PLAYBACK_VOLUME1
},
{
1
,
CAPTURE_CONTROL
},
};
void
snd_ca0106_mixer_suspend
(
struct
snd_ca0106
*
chip
)
{
int
i
;
/* save volumes */
for
(
i
=
0
;
i
<
NUM_SAVED_VOLUMES
;
i
++
)
chip
->
saved_vol
[
i
]
=
snd_ca0106_ptr_read
(
chip
,
saved_volumes
[
i
].
reg
,
saved_volumes
[
i
].
channel_id
);
}
void
snd_ca0106_mixer_resume
(
struct
snd_ca0106
*
chip
)
{
int
i
;
for
(
i
=
0
;
i
<
NUM_SAVED_VOLUMES
;
i
++
)
snd_ca0106_ptr_write
(
chip
,
saved_volumes
[
i
].
reg
,
saved_volumes
[
i
].
channel_id
,
chip
->
saved_vol
[
i
]);
ca0106_spdif_enable
(
chip
);
ca0106_set_capture_source
(
chip
);
ca0106_set_i2c_capture_source
(
chip
,
chip
->
i2c_capture_source
,
1
);
for
(
i
=
0
;
i
<
4
;
i
++
)
ca0106_set_spdif_bits
(
chip
,
i
);
if
(
chip
->
details
->
i2c_adc
)
ca0106_set_capture_mic_line_in
(
chip
);
}
#endif
/* CONFIG_PM */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment