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
Kirill Smelkov
linux
Commits
6129daaa
Commit
6129daaa
authored
Apr 09, 2006
by
James Courtier-Dutton
Committed by
Jaroslav Kysela
Jun 22, 2006
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[ALSA] ca0106: Add analog capture controls.
Signed-off-by:
James Courtier-Dutton
<
James@superbug.co.uk
>
parent
52ab3f3d
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
186 additions
and
14 deletions
+186
-14
sound/pci/ca0106/ca0106.h
sound/pci/ca0106/ca0106.h
+3
-1
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_main.c
+40
-4
sound/pci/ca0106/ca0106_mixer.c
sound/pci/ca0106/ca0106_mixer.c
+143
-9
No files found.
sound/pci/ca0106/ca0106.h
View file @
6129daaa
...
...
@@ -537,9 +537,9 @@
#endif
#define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux
#define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used)
#define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux
#define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux
#define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used)
#define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux
#define SET_CHANNEL 0
/* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
...
...
@@ -604,6 +604,8 @@ struct snd_ca0106 {
u32
spdif_bits
[
4
];
/* s/pdif out setup */
int
spdif_enable
;
int
capture_source
;
int
i2c_capture_source
;
u8
i2c_capture_volume
[
4
][
2
];
int
capture_mic_line_in
;
struct
snd_dma_buffer
buffer
;
...
...
sound/pci/ca0106/ca0106_main.c
View file @
6129daaa
...
...
@@ -326,6 +326,7 @@ int snd_ca0106_spi_write(struct snd_ca0106 * emu,
return
0
;
}
/* The ADC does not support i2c read, so only write is implemented */
int
snd_ca0106_i2c_write
(
struct
snd_ca0106
*
emu
,
u32
reg
,
u32
value
)
...
...
@@ -340,6 +341,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
}
tmp
=
reg
<<
25
|
value
<<
16
;
// snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
/* Not sure what this I2C channel controls. */
/* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
...
...
@@ -348,8 +350,9 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
for
(
retry
=
0
;
retry
<
10
;
retry
++
)
{
/* Send the data to i2c */
tmp
=
snd_ca0106_ptr_read
(
emu
,
I2C_A
,
0
);
tmp
=
tmp
&
~
(
I2C_A_ADC_READ
|
I2C_A_ADC_LAST
|
I2C_A_ADC_START
|
I2C_A_ADC_ADD_MASK
);
//tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
//tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
tmp
=
0
;
tmp
=
tmp
|
(
I2C_A_ADC_LAST
|
I2C_A_ADC_START
|
I2C_A_ADC_ADD
);
snd_ca0106_ptr_write
(
emu
,
I2C_A
,
0
,
tmp
);
...
...
@@ -1200,6 +1203,22 @@ static unsigned int spi_dac_init[] = {
0x1400
,
};
static
unsigned
int
i2c_adc_init
[][
2
]
=
{
{
0x17
,
0x00
},
/* Reset */
{
0x07
,
0x00
},
/* Timeout */
{
0x0b
,
0x22
},
/* Interface control */
{
0x0c
,
0x22
},
/* Master mode control */
{
0x0d
,
0x08
},
/* Powerdown control */
{
0x0e
,
0xcf
},
/* Attenuation Left 0x01 = -103dB, 0xff = 24dB */
{
0x0f
,
0xcf
},
/* Attenuation Right 0.5dB steps */
{
0x10
,
0x7b
},
/* ALC Control 1 */
{
0x11
,
0x00
},
/* ALC Control 2 */
{
0x12
,
0x32
},
/* ALC Control 3 */
{
0x13
,
0x00
},
/* Noise gate control */
{
0x14
,
0xa6
},
/* Limiter control */
{
0x15
,
ADC_MUX_LINEIN
},
/* ADC Mixer control */
};
static
int
__devinit
snd_ca0106_create
(
struct
snd_card
*
card
,
struct
pci_dev
*
pci
,
struct
snd_ca0106
**
rchip
)
...
...
@@ -1361,7 +1380,12 @@ static int __devinit snd_ca0106_create(struct snd_card *card,
snd_ca0106_ptr_write
(
chip
,
CAPTURE_SOURCE
,
0x0
,
0x333300e4
);
/* Select MIC, Line in, TAD in, AUX in */
chip
->
capture_source
=
3
;
/* Set CAPTURE_SOURCE */
if
(
chip
->
details
->
gpio_type
==
1
)
{
/* The SB0410 and SB0413 use GPIO differently. */
if
(
chip
->
details
->
gpio_type
==
2
)
{
/* 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
(
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. */
outl
(
0x0
,
chip
->
port
+
GPIO
);
//outl(0x00f0e000, chip->port+GPIO); /* Analog */
...
...
@@ -1379,7 +1403,19 @@ static int __devinit snd_ca0106_create(struct snd_card *card,
outl
(
HCFG_AC97
|
HCFG_AUDIOENABLE
,
chip
->
port
+
HCFG
);
/* AC97 2.0, Enable outputs. */
if
(
chip
->
details
->
i2c_adc
==
1
)
{
/* The SB0410 and SB0413 use I2C to control ADC. */
snd_ca0106_i2c_write
(
chip
,
ADC_MUX
,
ADC_MUX_LINEIN
);
/* Enable Line-in capture. MIC in currently untested. */
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
;
}
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. */
}
if
(
chip
->
details
->
spi_dac
==
1
)
{
/* The SB0570 use SPI to control DAC. */
int
size
,
n
;
...
...
sound/pci/ca0106/ca0106_mixer.c
View file @
6129daaa
...
...
@@ -171,6 +171,62 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
return
change
;
}
static
int
snd_ca0106_i2c_capture_source_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
static
char
*
texts
[
6
]
=
{
"Phone"
,
"Mic"
,
"Line in"
,
"Aux"
};
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
uinfo
->
count
=
1
;
uinfo
->
value
.
enumerated
.
items
=
4
;
if
(
uinfo
->
value
.
enumerated
.
item
>
3
)
uinfo
->
value
.
enumerated
.
item
=
3
;
strcpy
(
uinfo
->
value
.
enumerated
.
name
,
texts
[
uinfo
->
value
.
enumerated
.
item
]);
return
0
;
}
static
int
snd_ca0106_i2c_capture_source_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_ca0106
*
emu
=
snd_kcontrol_chip
(
kcontrol
);
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
emu
->
i2c_capture_source
;
return
0
;
}
static
int
snd_ca0106_i2c_capture_source_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
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.
*/
source_id
=
ucontrol
->
value
.
enumerated
.
item
[
0
]
;
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
;
}
return
change
;
}
static
int
snd_ca0106_capture_mic_line_in_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
...
...
@@ -207,16 +263,16 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
if
(
change
)
{
emu
->
capture_mic_line_in
=
val
;
if
(
val
)
{
snd_ca0106_i2c_write
(
emu
,
ADC_MUX
,
ADC_MUX_PHONE
);
/* Mute input */
//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
);
//
snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
}
else
{
snd_ca0106_i2c_write
(
emu
,
ADC_MUX
,
ADC_MUX_PHONE
);
/* Mute input */
//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
);
//
snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
}
}
return
change
;
...
...
@@ -225,7 +281,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
static
struct
snd_kcontrol_new
snd_ca0106_capture_mic_line_in
__devinitdata
=
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"
Mic/Line in Capture
"
,
.
name
=
"
Shared Mic/Line in Capture Switch
"
,
.
info
=
snd_ca0106_capture_mic_line_in_info
,
.
get
=
snd_ca0106_capture_mic_line_in_get
,
.
put
=
snd_ca0106_capture_mic_line_in_put
...
...
@@ -329,15 +385,81 @@ static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
return
1
;
}
static
int
snd_ca0106_i2c_volume_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
uinfo
->
count
=
2
;
uinfo
->
value
.
integer
.
min
=
0
;
uinfo
->
value
.
integer
.
max
=
255
;
return
0
;
}
static
int
snd_ca0106_i2c_volume_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_ca0106
*
emu
=
snd_kcontrol_chip
(
kcontrol
);
int
source_id
;
source_id
=
kcontrol
->
private_value
;
ucontrol
->
value
.
integer
.
value
[
0
]
=
emu
->
i2c_capture_volume
[
source_id
][
0
];
ucontrol
->
value
.
integer
.
value
[
1
]
=
emu
->
i2c_capture_volume
[
source_id
][
1
];
return
0
;
}
static
int
snd_ca0106_i2c_volume_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_ca0106
*
emu
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
int
ogain
;
unsigned
int
ngain
;
int
source_id
;
int
change
=
0
;
source_id
=
kcontrol
->
private_value
;
ogain
=
emu
->
i2c_capture_volume
[
source_id
][
0
];
/* Left */
ngain
=
ucontrol
->
value
.
integer
.
value
[
0
];
if
(
ngain
>
0xff
)
return
0
;
if
(
ogain
!=
ngain
)
{
if
(
emu
->
i2c_capture_source
==
source_id
)
snd_ca0106_i2c_write
(
emu
,
ADC_ATTEN_ADCL
,
((
ngain
)
&
0xff
)
);
emu
->
i2c_capture_volume
[
source_id
][
0
]
=
ucontrol
->
value
.
integer
.
value
[
0
];
change
=
1
;
}
ogain
=
emu
->
i2c_capture_volume
[
source_id
][
1
];
/* Right */
ngain
=
ucontrol
->
value
.
integer
.
value
[
1
];
if
(
ngain
>
0xff
)
return
0
;
if
(
ogain
!=
ngain
)
{
if
(
emu
->
i2c_capture_source
==
source_id
)
snd_ca0106_i2c_write
(
emu
,
ADC_ATTEN_ADCR
,
((
ngain
)
&
0xff
));
emu
->
i2c_capture_volume
[
source_id
][
1
]
=
ucontrol
->
value
.
integer
.
value
[
1
];
change
=
1
;
}
return
change
;
}
#define CA_VOLUME(xname,chid,reg) \
{ \
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info =
snd_ca0106_volume_info,
\
.get =
snd_ca0106_volume_get,
\
.put =
snd_ca0106_volume_put,
\
.info =
snd_ca0106_volume_info,
\
.get =
snd_ca0106_volume_get,
\
.put =
snd_ca0106_volume_put,
\
.private_value = ((chid) << 8) | (reg) \
}
#define I2C_VOLUME(xname,chid) \
{ \
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_ca0106_i2c_volume_info, \
.get = snd_ca0106_i2c_volume_get, \
.put = snd_ca0106_i2c_volume_put, \
.private_value = chid \
}
static
struct
snd_kcontrol_new
snd_ca0106_volume_ctls
[]
__devinitdata
=
{
CA_VOLUME
(
"Analog Front Playback Volume"
,
...
...
@@ -361,6 +483,11 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
CA_VOLUME
(
"CAPTURE feedback Playback Volume"
,
1
,
CAPTURE_CONTROL
),
I2C_VOLUME
(
"Phone Capture Volume"
,
0
),
I2C_VOLUME
(
"Mic Capture Volume"
,
1
),
I2C_VOLUME
(
"Line in Capture Volume"
,
2
),
I2C_VOLUME
(
"Aux Capture Volume"
,
3
),
{
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
,
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
...
...
@@ -378,11 +505,18 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Capture Source"
,
.
name
=
"
Digital
Capture Source"
,
.
info
=
snd_ca0106_capture_source_info
,
.
get
=
snd_ca0106_capture_source_get
,
.
put
=
snd_ca0106_capture_source_put
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Capture Source"
,
.
info
=
snd_ca0106_i2c_capture_source_info
,
.
get
=
snd_ca0106_i2c_capture_source_get
,
.
put
=
snd_ca0106_i2c_capture_source_put
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
SNDRV_CTL_NAME_IEC958
(
""
,
PLAYBACK
,
DEFAULT
),
...
...
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