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
e0274b0a
Commit
e0274b0a
authored
Sep 21, 2009
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'upstream/wm8711' into for-2.6.33
parents
d62ab358
b5ab887e
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
706 additions
and
0 deletions
+706
-0
sound/soc/codecs/Kconfig
sound/soc/codecs/Kconfig
+4
-0
sound/soc/codecs/Makefile
sound/soc/codecs/Makefile
+2
-0
sound/soc/codecs/wm8711.c
sound/soc/codecs/wm8711.c
+658
-0
sound/soc/codecs/wm8711.h
sound/soc/codecs/wm8711.h
+42
-0
No files found.
sound/soc/codecs/Kconfig
View file @
e0274b0a
...
...
@@ -37,6 +37,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8523 if I2C
select SND_SOC_WM8580 if I2C
select SND_SOC_WM8711 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
...
...
@@ -164,6 +165,9 @@ config SND_SOC_WM8523
config SND_SOC_WM8580
tristate
config SND_SOC_WM8711
tristate
config SND_SOC_WM8728
tristate
...
...
sound/soc/codecs/Makefile
View file @
e0274b0a
...
...
@@ -25,6 +25,7 @@ snd-soc-wm8400-objs := wm8400.o
snd-soc-wm8510-objs
:=
wm8510.o
snd-soc-wm8523-objs
:=
wm8523.o
snd-soc-wm8580-objs
:=
wm8580.o
snd-soc-wm8711-objs
:=
wm8711.o
snd-soc-wm8728-objs
:=
wm8728.o
snd-soc-wm8731-objs
:=
wm8731.o
snd-soc-wm8750-objs
:=
wm8750.o
...
...
@@ -76,6 +77,7 @@ obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
obj-$(CONFIG_SND_SOC_WM8510)
+=
snd-soc-wm8510.o
obj-$(CONFIG_SND_SOC_WM8523)
+=
snd-soc-wm8523.o
obj-$(CONFIG_SND_SOC_WM8580)
+=
snd-soc-wm8580.o
obj-$(CONFIG_SND_SOC_WM8711)
+=
snd-soc-wm8711.o
obj-$(CONFIG_SND_SOC_WM8728)
+=
snd-soc-wm8728.o
obj-$(CONFIG_SND_SOC_WM8731)
+=
snd-soc-wm8731.o
obj-$(CONFIG_SND_SOC_WM8750)
+=
snd-soc-wm8750.o
...
...
sound/soc/codecs/wm8711.c
0 → 100644
View file @
e0274b0a
/*
* wm8711.c -- WM8711 ALSA SoC Audio driver
*
* Copyright 2006 Wolfson Microelectronics
*
* Author: Mike Arthur <linux@wolfsonmicro.com>
*
* Based on wm8731.c by Richard Purdie
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include <sound/initval.h>
#include "wm8711.h"
static
struct
snd_soc_codec
*
wm8711_codec
;
/* codec private data */
struct
wm8711_priv
{
struct
snd_soc_codec
codec
;
u16
reg_cache
[
WM8711_CACHEREGNUM
];
unsigned
int
sysclk
;
};
/*
* wm8711 register cache
* We can't read the WM8711 register space when we are
* using 2 wire for device control, so we cache them instead.
* There is no point in caching the reset register
*/
static
const
u16
wm8711_reg
[
WM8711_CACHEREGNUM
]
=
{
0x0079
,
0x0079
,
0x000a
,
0x0008
,
0x009f
,
0x000a
,
0x0000
,
0x0000
};
#define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0)
static
const
DECLARE_TLV_DB_SCALE
(
out_tlv
,
-
12100
,
100
,
1
);
static
const
struct
snd_kcontrol_new
wm8711_snd_controls
[]
=
{
SOC_DOUBLE_R_TLV
(
"Master Playback Volume"
,
WM8711_LOUT1V
,
WM8711_ROUT1V
,
0
,
127
,
0
,
out_tlv
),
SOC_DOUBLE_R
(
"Master Playback ZC Switch"
,
WM8711_LOUT1V
,
WM8711_ROUT1V
,
7
,
1
,
0
),
};
/* Output Mixer */
static
const
struct
snd_kcontrol_new
wm8711_output_mixer_controls
[]
=
{
SOC_DAPM_SINGLE
(
"Line Bypass Switch"
,
WM8711_APANA
,
3
,
1
,
0
),
SOC_DAPM_SINGLE
(
"HiFi Playback Switch"
,
WM8711_APANA
,
4
,
1
,
0
),
};
static
const
struct
snd_soc_dapm_widget
wm8711_dapm_widgets
[]
=
{
SND_SOC_DAPM_MIXER
(
"Output Mixer"
,
WM8711_PWR
,
4
,
1
,
&
wm8711_output_mixer_controls
[
0
],
ARRAY_SIZE
(
wm8711_output_mixer_controls
)),
SND_SOC_DAPM_DAC
(
"DAC"
,
"HiFi Playback"
,
WM8711_PWR
,
3
,
1
),
SND_SOC_DAPM_OUTPUT
(
"LOUT"
),
SND_SOC_DAPM_OUTPUT
(
"LHPOUT"
),
SND_SOC_DAPM_OUTPUT
(
"ROUT"
),
SND_SOC_DAPM_OUTPUT
(
"RHPOUT"
),
};
static
const
struct
snd_soc_dapm_route
intercon
[]
=
{
/* output mixer */
{
"Output Mixer"
,
"Line Bypass Switch"
,
"Line Input"
},
{
"Output Mixer"
,
"HiFi Playback Switch"
,
"DAC"
},
/* outputs */
{
"RHPOUT"
,
NULL
,
"Output Mixer"
},
{
"ROUT"
,
NULL
,
"Output Mixer"
},
{
"LHPOUT"
,
NULL
,
"Output Mixer"
},
{
"LOUT"
,
NULL
,
"Output Mixer"
},
};
static
int
wm8711_add_widgets
(
struct
snd_soc_codec
*
codec
)
{
snd_soc_dapm_new_controls
(
codec
,
wm8711_dapm_widgets
,
ARRAY_SIZE
(
wm8711_dapm_widgets
));
snd_soc_dapm_add_routes
(
codec
,
intercon
,
ARRAY_SIZE
(
intercon
));
snd_soc_dapm_new_widgets
(
codec
);
return
0
;
}
struct
_coeff_div
{
u32
mclk
;
u32
rate
;
u16
fs
;
u8
sr
:
4
;
u8
bosr
:
1
;
u8
usb
:
1
;
};
/* codec mclk clock divider coefficients */
static
const
struct
_coeff_div
coeff_div
[]
=
{
/* 48k */
{
12288000
,
48000
,
256
,
0x0
,
0x0
,
0x0
},
{
18432000
,
48000
,
384
,
0x0
,
0x1
,
0x0
},
{
12000000
,
48000
,
250
,
0x0
,
0x0
,
0x1
},
/* 32k */
{
12288000
,
32000
,
384
,
0x6
,
0x0
,
0x0
},
{
18432000
,
32000
,
576
,
0x6
,
0x1
,
0x0
},
{
12000000
,
32000
,
375
,
0x6
,
0x0
,
0x1
},
/* 8k */
{
12288000
,
8000
,
1536
,
0x3
,
0x0
,
0x0
},
{
18432000
,
8000
,
2304
,
0x3
,
0x1
,
0x0
},
{
11289600
,
8000
,
1408
,
0xb
,
0x0
,
0x0
},
{
16934400
,
8000
,
2112
,
0xb
,
0x1
,
0x0
},
{
12000000
,
8000
,
1500
,
0x3
,
0x0
,
0x1
},
/* 96k */
{
12288000
,
96000
,
128
,
0x7
,
0x0
,
0x0
},
{
18432000
,
96000
,
192
,
0x7
,
0x1
,
0x0
},
{
12000000
,
96000
,
125
,
0x7
,
0x0
,
0x1
},
/* 44.1k */
{
11289600
,
44100
,
256
,
0x8
,
0x0
,
0x0
},
{
16934400
,
44100
,
384
,
0x8
,
0x1
,
0x0
},
{
12000000
,
44100
,
272
,
0x8
,
0x1
,
0x1
},
/* 88.2k */
{
11289600
,
88200
,
128
,
0xf
,
0x0
,
0x0
},
{
16934400
,
88200
,
192
,
0xf
,
0x1
,
0x0
},
{
12000000
,
88200
,
136
,
0xf
,
0x1
,
0x1
},
};
static
inline
int
get_coeff
(
int
mclk
,
int
rate
)
{
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
coeff_div
);
i
++
)
{
if
(
coeff_div
[
i
].
rate
==
rate
&&
coeff_div
[
i
].
mclk
==
mclk
)
return
i
;
}
return
0
;
}
static
int
wm8711_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
struct
wm8711_priv
*
wm8711
=
codec
->
private_data
;
u16
iface
=
snd_soc_read
(
codec
,
WM8711_IFACE
)
&
0xfffc
;
int
i
=
get_coeff
(
wm8711
->
sysclk
,
params_rate
(
params
));
u16
srate
=
(
coeff_div
[
i
].
sr
<<
2
)
|
(
coeff_div
[
i
].
bosr
<<
1
)
|
coeff_div
[
i
].
usb
;
snd_soc_write
(
codec
,
WM8711_SRATE
,
srate
);
/* bit size */
switch
(
params_format
(
params
))
{
case
SNDRV_PCM_FORMAT_S16_LE
:
break
;
case
SNDRV_PCM_FORMAT_S20_3LE
:
iface
|=
0x0004
;
break
;
case
SNDRV_PCM_FORMAT_S24_LE
:
iface
|=
0x0008
;
break
;
}
snd_soc_write
(
codec
,
WM8711_IFACE
,
iface
);
return
0
;
}
static
int
wm8711_pcm_prepare
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
dai
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
/* set active */
snd_soc_write
(
codec
,
WM8711_ACTIVE
,
0x0001
);
return
0
;
}
static
void
wm8711_shutdown
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
dai
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
/* deactivate */
if
(
!
codec
->
active
)
{
udelay
(
50
);
snd_soc_write
(
codec
,
WM8711_ACTIVE
,
0x0
);
}
}
static
int
wm8711_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
mute_reg
=
snd_soc_read
(
codec
,
WM8711_APDIGI
)
&
0xfff7
;
if
(
mute
)
snd_soc_write
(
codec
,
WM8711_APDIGI
,
mute_reg
|
0x8
);
else
snd_soc_write
(
codec
,
WM8711_APDIGI
,
mute_reg
);
return
0
;
}
static
int
wm8711_set_dai_sysclk
(
struct
snd_soc_dai
*
codec_dai
,
int
clk_id
,
unsigned
int
freq
,
int
dir
)
{
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
struct
wm8711_priv
*
wm8711
=
codec
->
private_data
;
switch
(
freq
)
{
case
11289600
:
case
12000000
:
case
12288000
:
case
16934400
:
case
18432000
:
wm8711
->
sysclk
=
freq
;
return
0
;
}
return
-
EINVAL
;
}
static
int
wm8711_set_dai_fmt
(
struct
snd_soc_dai
*
codec_dai
,
unsigned
int
fmt
)
{
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
u16
iface
=
0
;
/* set master/slave audio interface */
switch
(
fmt
&
SND_SOC_DAIFMT_MASTER_MASK
)
{
case
SND_SOC_DAIFMT_CBM_CFM
:
iface
|=
0x0040
;
break
;
case
SND_SOC_DAIFMT_CBS_CFS
:
break
;
default:
return
-
EINVAL
;
}
/* interface format */
switch
(
fmt
&
SND_SOC_DAIFMT_FORMAT_MASK
)
{
case
SND_SOC_DAIFMT_I2S
:
iface
|=
0x0002
;
break
;
case
SND_SOC_DAIFMT_RIGHT_J
:
break
;
case
SND_SOC_DAIFMT_LEFT_J
:
iface
|=
0x0001
;
break
;
case
SND_SOC_DAIFMT_DSP_A
:
iface
|=
0x0003
;
break
;
case
SND_SOC_DAIFMT_DSP_B
:
iface
|=
0x0013
;
break
;
default:
return
-
EINVAL
;
}
/* clock inversion */
switch
(
fmt
&
SND_SOC_DAIFMT_INV_MASK
)
{
case
SND_SOC_DAIFMT_NB_NF
:
break
;
case
SND_SOC_DAIFMT_IB_IF
:
iface
|=
0x0090
;
break
;
case
SND_SOC_DAIFMT_IB_NF
:
iface
|=
0x0080
;
break
;
case
SND_SOC_DAIFMT_NB_IF
:
iface
|=
0x0010
;
break
;
default:
return
-
EINVAL
;
}
/* set iface */
snd_soc_write
(
codec
,
WM8711_IFACE
,
iface
);
return
0
;
}
static
int
wm8711_set_bias_level
(
struct
snd_soc_codec
*
codec
,
enum
snd_soc_bias_level
level
)
{
u16
reg
=
snd_soc_read
(
codec
,
WM8711_PWR
)
&
0xff7f
;
switch
(
level
)
{
case
SND_SOC_BIAS_ON
:
snd_soc_write
(
codec
,
WM8711_PWR
,
reg
);
break
;
case
SND_SOC_BIAS_PREPARE
:
break
;
case
SND_SOC_BIAS_STANDBY
:
snd_soc_write
(
codec
,
WM8711_PWR
,
reg
|
0x0040
);
break
;
case
SND_SOC_BIAS_OFF
:
snd_soc_write
(
codec
,
WM8711_ACTIVE
,
0x0
);
snd_soc_write
(
codec
,
WM8711_PWR
,
0xffff
);
break
;
}
codec
->
bias_level
=
level
;
return
0
;
}
#define WM8711_RATES SNDRV_PCM_RATE_8000_96000
#define WM8711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
static
struct
snd_soc_dai_ops
wm8711_ops
=
{
.
prepare
=
wm8711_pcm_prepare
,
.
hw_params
=
wm8711_hw_params
,
.
shutdown
=
wm8711_shutdown
,
.
digital_mute
=
wm8711_mute
,
.
set_sysclk
=
wm8711_set_dai_sysclk
,
.
set_fmt
=
wm8711_set_dai_fmt
,
};
struct
snd_soc_dai
wm8711_dai
=
{
.
name
=
"WM8711"
,
.
playback
=
{
.
stream_name
=
"Playback"
,
.
channels_min
=
1
,
.
channels_max
=
2
,
.
rates
=
WM8711_RATES
,
.
formats
=
WM8711_FORMATS
,
},
.
ops
=
&
wm8711_ops
,
};
EXPORT_SYMBOL_GPL
(
wm8711_dai
);
static
int
wm8711_suspend
(
struct
platform_device
*
pdev
,
pm_message_t
state
)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
snd_soc_write
(
codec
,
WM8711_ACTIVE
,
0x0
);
wm8711_set_bias_level
(
codec
,
SND_SOC_BIAS_OFF
);
return
0
;
}
static
int
wm8711_resume
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
int
i
;
u8
data
[
2
];
u16
*
cache
=
codec
->
reg_cache
;
/* Sync reg_cache with the hardware */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8711_reg
);
i
++
)
{
data
[
0
]
=
(
i
<<
1
)
|
((
cache
[
i
]
>>
8
)
&
0x0001
);
data
[
1
]
=
cache
[
i
]
&
0x00ff
;
codec
->
hw_write
(
codec
->
control_data
,
data
,
2
);
}
wm8711_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
wm8711_set_bias_level
(
codec
,
codec
->
suspend_bias_level
);
return
0
;
}
static
int
wm8711_probe
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
struct
snd_soc_codec
*
codec
;
int
ret
=
0
;
if
(
wm8711_codec
==
NULL
)
{
dev_err
(
&
pdev
->
dev
,
"Codec device not registered
\n
"
);
return
-
ENODEV
;
}
socdev
->
card
->
codec
=
wm8711_codec
;
codec
=
wm8711_codec
;
/* register pcms */
ret
=
snd_soc_new_pcms
(
socdev
,
SNDRV_DEFAULT_IDX1
,
SNDRV_DEFAULT_STR1
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"failed to create pcms: %d
\n
"
,
ret
);
goto
pcm_err
;
}
snd_soc_add_controls
(
codec
,
wm8711_snd_controls
,
ARRAY_SIZE
(
wm8711_snd_controls
));
wm8711_add_widgets
(
codec
);
ret
=
snd_soc_init_card
(
socdev
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"failed to register card: %d
\n
"
,
ret
);
goto
card_err
;
}
return
ret
;
card_err:
snd_soc_free_pcms
(
socdev
);
snd_soc_dapm_free
(
socdev
);
pcm_err:
return
ret
;
}
/* power down chip */
static
int
wm8711_remove
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
snd_soc_free_pcms
(
socdev
);
snd_soc_dapm_free
(
socdev
);
return
0
;
}
struct
snd_soc_codec_device
soc_codec_dev_wm8711
=
{
.
probe
=
wm8711_probe
,
.
remove
=
wm8711_remove
,
.
suspend
=
wm8711_suspend
,
.
resume
=
wm8711_resume
,
};
EXPORT_SYMBOL_GPL
(
soc_codec_dev_wm8711
);
static
int
wm8711_register
(
struct
wm8711_priv
*
wm8711
,
enum
snd_soc_control_type
control
)
{
int
ret
;
struct
snd_soc_codec
*
codec
=
&
wm8711
->
codec
;
u16
reg
;
if
(
wm8711_codec
)
{
dev_err
(
codec
->
dev
,
"Another WM8711 is registered
\n
"
);
return
-
EINVAL
;
}
mutex_init
(
&
codec
->
mutex
);
INIT_LIST_HEAD
(
&
codec
->
dapm_widgets
);
INIT_LIST_HEAD
(
&
codec
->
dapm_paths
);
codec
->
private_data
=
wm8711
;
codec
->
name
=
"WM8711"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
bias_level
=
SND_SOC_BIAS_OFF
;
codec
->
set_bias_level
=
wm8711_set_bias_level
;
codec
->
dai
=
&
wm8711_dai
;
codec
->
num_dai
=
1
;
codec
->
reg_cache_size
=
WM8711_CACHEREGNUM
;
codec
->
reg_cache
=
&
wm8711
->
reg_cache
;
memcpy
(
codec
->
reg_cache
,
wm8711_reg
,
sizeof
(
wm8711_reg
));
ret
=
snd_soc_codec_set_cache_io
(
codec
,
7
,
9
,
control
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
ret
=
wm8711_reset
(
codec
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to issue reset
\n
"
);
goto
err
;
}
wm8711_dai
.
dev
=
codec
->
dev
;
wm8711_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
/* Latch the update bits */
reg
=
snd_soc_read
(
codec
,
WM8711_LOUT1V
);
snd_soc_write
(
codec
,
WM8711_LOUT1V
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8711_ROUT1V
);
snd_soc_write
(
codec
,
WM8711_ROUT1V
,
reg
|
0x0100
);
wm8711_codec
=
codec
;
ret
=
snd_soc_register_codec
(
codec
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to register codec: %d
\n
"
,
ret
);
goto
err
;
}
ret
=
snd_soc_register_dai
(
&
wm8711_dai
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to register DAI: %d
\n
"
,
ret
);
goto
err_codec
;
}
return
0
;
err_codec:
snd_soc_unregister_codec
(
codec
);
err:
kfree
(
wm8711
);
return
ret
;
}
static
void
wm8711_unregister
(
struct
wm8711_priv
*
wm8711
)
{
wm8711_set_bias_level
(
&
wm8711
->
codec
,
SND_SOC_BIAS_OFF
);
snd_soc_unregister_dai
(
&
wm8711_dai
);
snd_soc_unregister_codec
(
&
wm8711
->
codec
);
kfree
(
wm8711
);
wm8711_codec
=
NULL
;
}
#if defined(CONFIG_SPI_MASTER)
static
int
__devinit
wm8711_spi_probe
(
struct
spi_device
*
spi
)
{
struct
snd_soc_codec
*
codec
;
struct
wm8711_priv
*
wm8711
;
wm8711
=
kzalloc
(
sizeof
(
struct
wm8711_priv
),
GFP_KERNEL
);
if
(
wm8711
==
NULL
)
return
-
ENOMEM
;
codec
=
&
wm8711
->
codec
;
codec
->
control_data
=
spi
;
codec
->
dev
=
&
spi
->
dev
;
dev_set_drvdata
(
&
spi
->
dev
,
wm8711
);
return
wm8711_register
(
wm8711
,
SND_SOC_SPI
);
}
static
int
__devexit
wm8711_spi_remove
(
struct
spi_device
*
spi
)
{
struct
wm8711_priv
*
wm8711
=
dev_get_drvdata
(
&
spi
->
dev
);
wm8711_unregister
(
wm8711
);
return
0
;
}
#ifdef CONFIG_PM
static
int
wm8711_spi_suspend
(
struct
spi_device
*
spi
,
pm_message_t
msg
)
{
return
snd_soc_suspend_device
(
&
spi
->
dev
);
}
static
int
wm8711_spi_resume
(
struct
spi_device
*
spi
)
{
return
snd_soc_resume_device
(
&
spi
->
dev
);
}
#else
#define wm8711_spi_suspend NULL
#define wm8711_spi_resume NULL
#endif
static
struct
spi_driver
wm8711_spi_driver
=
{
.
driver
=
{
.
name
=
"wm8711"
,
.
bus
=
&
spi_bus_type
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
wm8711_spi_probe
,
.
suspend
=
wm8711_spi_suspend
,
.
resume
=
wm8711_spi_resume
,
.
remove
=
__devexit_p
(
wm8711_spi_remove
),
};
#endif
/* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static
__devinit
int
wm8711_i2c_probe
(
struct
i2c_client
*
i2c
,
const
struct
i2c_device_id
*
id
)
{
struct
wm8711_priv
*
wm8711
;
struct
snd_soc_codec
*
codec
;
wm8711
=
kzalloc
(
sizeof
(
struct
wm8711_priv
),
GFP_KERNEL
);
if
(
wm8711
==
NULL
)
return
-
ENOMEM
;
codec
=
&
wm8711
->
codec
;
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
i2c_set_clientdata
(
i2c
,
wm8711
);
codec
->
control_data
=
i2c
;
codec
->
dev
=
&
i2c
->
dev
;
return
wm8711_register
(
wm8711
,
SND_SOC_I2C
);
}
static
__devexit
int
wm8711_i2c_remove
(
struct
i2c_client
*
client
)
{
struct
wm8711_priv
*
wm8711
=
i2c_get_clientdata
(
client
);
wm8711_unregister
(
wm8711
);
return
0
;
}
static
const
struct
i2c_device_id
wm8711_i2c_id
[]
=
{
{
"wm8711"
,
0
},
{
}
};
MODULE_DEVICE_TABLE
(
i2c
,
wm8711_i2c_id
);
static
struct
i2c_driver
wm8711_i2c_driver
=
{
.
driver
=
{
.
name
=
"WM8711 I2C Codec"
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
wm8711_i2c_probe
,
.
remove
=
__devexit_p
(
wm8711_i2c_remove
),
.
id_table
=
wm8711_i2c_id
,
};
#endif
static
int
__init
wm8711_modinit
(
void
)
{
int
ret
;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret
=
i2c_add_driver
(
&
wm8711_i2c_driver
);
if
(
ret
!=
0
)
{
printk
(
KERN_ERR
"Failed to register WM8711 I2C driver: %d
\n
"
,
ret
);
}
#endif
#if defined(CONFIG_SPI_MASTER)
ret
=
spi_register_driver
(
&
wm8731_spi_driver
);
if
(
ret
!=
0
)
{
printk
(
KERN_ERR
"Failed to register WM8731 SPI driver: %d
\n
"
,
ret
);
}
#endif
return
0
;
}
module_init
(
wm8711_modinit
);
static
void
__exit
wm8711_exit
(
void
)
{
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver
(
&
wm8711_i2c_driver
);
#endif
#if defined(CONFIG_SPI_MASTER)
spi_unregister_driver
(
&
wm8731_spi_driver
);
#endif
}
module_exit
(
wm8711_exit
);
MODULE_DESCRIPTION
(
"ASoC WM8711 driver"
);
MODULE_AUTHOR
(
"Mike Arthur"
);
MODULE_LICENSE
(
"GPL"
);
sound/soc/codecs/wm8711.h
0 → 100644
View file @
e0274b0a
/*
* wm8711.h -- WM8711 Soc Audio driver
*
* Copyright 2006 Wolfson Microelectronics
*
* Author: Mike Arthur <linux@wolfsonmicro.com>
*
* Based on wm8731.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _WM8711_H
#define _WM8711_H
/* WM8711 register space */
#define WM8711_LOUT1V 0x02
#define WM8711_ROUT1V 0x03
#define WM8711_APANA 0x04
#define WM8711_APDIGI 0x05
#define WM8711_PWR 0x06
#define WM8711_IFACE 0x07
#define WM8711_SRATE 0x08
#define WM8711_ACTIVE 0x09
#define WM8711_RESET 0x0f
#define WM8711_CACHEREGNUM 8
#define WM8711_SYSCLK 0
#define WM8711_DAI 0
struct
wm8711_setup_data
{
unsigned
short
i2c_address
;
};
extern
struct
snd_soc_dai
wm8711_dai
;
extern
struct
snd_soc_codec_device
soc_codec_dev_wm8711
;
#endif
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