Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
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