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
9713d5d0
Commit
9713d5d0
authored
Jun 03, 2014
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branches 'asoc/topic/gpio' and 'asoc/topic/intel' into asoc-next
parents
1ecf4450
e667487b
d8188f00
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
319 additions
and
67 deletions
+319
-67
include/sound/soc.h
include/sound/soc.h
+20
-2
sound/soc/intel/Kconfig
sound/soc/intel/Kconfig
+9
-0
sound/soc/intel/Makefile
sound/soc/intel/Makefile
+2
-0
sound/soc/intel/byt-max98090.c
sound/soc/intel/byt-max98090.c
+203
-0
sound/soc/intel/byt-rt5640.c
sound/soc/intel/byt-rt5640.c
+2
-25
sound/soc/intel/haswell.c
sound/soc/intel/haswell.c
+1
-8
sound/soc/intel/sst-acpi.c
sound/soc/intel/sst-acpi.c
+1
-0
sound/soc/intel/sst-baytrail-ipc.c
sound/soc/intel/sst-baytrail-ipc.c
+5
-3
sound/soc/intel/sst-baytrail-pcm.c
sound/soc/intel/sst-baytrail-pcm.c
+1
-0
sound/soc/intel/sst-haswell-ipc.c
sound/soc/intel/sst-haswell-ipc.c
+9
-6
sound/soc/intel/sst-haswell-pcm.c
sound/soc/intel/sst-haswell-pcm.c
+0
-1
sound/soc/soc-jack.c
sound/soc/soc-jack.c
+66
-22
No files found.
include/sound/soc.h
View file @
9713d5d0
...
...
@@ -452,6 +452,9 @@ int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage);
#ifdef CONFIG_GPIOLIB
int
snd_soc_jack_add_gpios
(
struct
snd_soc_jack
*
jack
,
int
count
,
struct
snd_soc_jack_gpio
*
gpios
);
int
snd_soc_jack_add_gpiods
(
struct
device
*
gpiod_dev
,
struct
snd_soc_jack
*
jack
,
int
count
,
struct
snd_soc_jack_gpio
*
gpios
);
void
snd_soc_jack_free_gpios
(
struct
snd_soc_jack
*
jack
,
int
count
,
struct
snd_soc_jack_gpio
*
gpios
);
#else
...
...
@@ -461,6 +464,14 @@ static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
return
0
;
}
static
inline
int
snd_soc_jack_add_gpiods
(
struct
device
*
gpiod_dev
,
struct
snd_soc_jack
*
jack
,
int
count
,
struct
snd_soc_jack_gpio
*
gpios
)
{
return
0
;
}
static
inline
void
snd_soc_jack_free_gpios
(
struct
snd_soc_jack
*
jack
,
int
count
,
struct
snd_soc_jack_gpio
*
gpios
)
{
...
...
@@ -587,8 +598,12 @@ struct snd_soc_jack_zone {
/**
* struct snd_soc_jack_gpio - Describes a gpio pin for jack detection
*
* @gpio: gpio number
* @name: gpio name
* @gpio: legacy gpio number
* @idx: gpio descriptor index within the function of the GPIO
* consumer device
* @gpiod_dev GPIO consumer device
* @name: gpio name. Also as connection ID for the GPIO consumer
* device function name lookup
* @report: value to report when jack detected
* @invert: report presence in low state
* @debouce_time: debouce time in ms
...
...
@@ -599,6 +614,8 @@ struct snd_soc_jack_zone {
*/
struct
snd_soc_jack_gpio
{
unsigned
int
gpio
;
unsigned
int
idx
;
struct
device
*
gpiod_dev
;
const
char
*
name
;
int
report
;
int
invert
;
...
...
@@ -607,6 +624,7 @@ struct snd_soc_jack_gpio {
struct
snd_soc_jack
*
jack
;
struct
delayed_work
work
;
struct
gpio_desc
*
desc
;
void
*
data
;
int
(
*
jack_status_check
)(
void
*
data
);
...
...
sound/soc/intel/Kconfig
View file @
9713d5d0
...
...
@@ -49,3 +49,12 @@ config SND_SOC_INTEL_BYT_RT5640_MACH
help
This adds audio driver for Intel Baytrail platform based boards
with the RT5640 audio codec.
config SND_SOC_INTEL_BYT_MAX98090_MACH
tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec"
depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C
select SND_SOC_INTEL_BAYTRAIL
select SND_SOC_MAX98090
help
This adds audio driver for Intel Baytrail platform based boards
with the MAX98090 audio codec.
sound/soc/intel/Makefile
View file @
9713d5d0
...
...
@@ -23,6 +23,8 @@ obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o
# Machine support
snd-soc-sst-haswell-objs
:=
haswell.o
snd-soc-sst-byt-rt5640-mach-objs
:=
byt-rt5640.o
snd-soc-sst-byt-max98090-mach-objs
:=
byt-max98090.o
obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH)
+=
snd-soc-sst-haswell.o
obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH)
+=
snd-soc-sst-byt-rt5640-mach.o
obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH)
+=
snd-soc-sst-byt-max98090-mach.o
sound/soc/intel/byt-max98090.c
0 → 100644
View file @
9713d5d0
/*
* Intel Baytrail SST MAX98090 machine driver
* Copyright (c) 2014, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/jack.h>
#include "../codecs/max98090.h"
struct
byt_max98090_private
{
struct
snd_soc_jack
jack
;
};
static
const
struct
snd_soc_dapm_widget
byt_max98090_widgets
[]
=
{
SND_SOC_DAPM_HP
(
"Headphone"
,
NULL
),
SND_SOC_DAPM_MIC
(
"Headset Mic"
,
NULL
),
SND_SOC_DAPM_MIC
(
"Int Mic"
,
NULL
),
SND_SOC_DAPM_SPK
(
"Ext Spk"
,
NULL
),
};
static
const
struct
snd_soc_dapm_route
byt_max98090_audio_map
[]
=
{
{
"IN34"
,
NULL
,
"Headset Mic"
},
{
"IN34"
,
NULL
,
"MICBIAS"
},
{
"MICBIAS"
,
NULL
,
"Headset Mic"
},
{
"DMICL"
,
NULL
,
"Int Mic"
},
{
"Headphone"
,
NULL
,
"HPL"
},
{
"Headphone"
,
NULL
,
"HPR"
},
{
"Ext Spk"
,
NULL
,
"SPKL"
},
{
"Ext Spk"
,
NULL
,
"SPKR"
},
};
static
const
struct
snd_kcontrol_new
byt_max98090_controls
[]
=
{
SOC_DAPM_PIN_SWITCH
(
"Headphone"
),
SOC_DAPM_PIN_SWITCH
(
"Headset Mic"
),
SOC_DAPM_PIN_SWITCH
(
"Int Mic"
),
SOC_DAPM_PIN_SWITCH
(
"Ext Spk"
),
};
static
struct
snd_soc_jack_pin
hs_jack_pins
[]
=
{
{
.
pin
=
"Headphone"
,
.
mask
=
SND_JACK_HEADPHONE
,
},
{
.
pin
=
"Headset Mic"
,
.
mask
=
SND_JACK_MICROPHONE
,
},
{
.
pin
=
"Ext Spk"
,
.
mask
=
SND_JACK_LINEOUT
,
},
{
.
pin
=
"Int Mic"
,
.
mask
=
SND_JACK_LINEIN
,
},
};
static
struct
snd_soc_jack_gpio
hs_jack_gpios
[]
=
{
{
.
name
=
"hp-gpio"
,
.
idx
=
0
,
.
report
=
SND_JACK_HEADPHONE
|
SND_JACK_LINEOUT
,
.
debounce_time
=
200
,
},
{
.
name
=
"mic-gpio"
,
.
idx
=
1
,
.
report
=
SND_JACK_MICROPHONE
|
SND_JACK_LINEIN
,
.
debounce_time
=
200
,
},
};
static
int
byt_max98090_init
(
struct
snd_soc_pcm_runtime
*
runtime
)
{
int
ret
;
struct
snd_soc_codec
*
codec
=
runtime
->
codec
;
struct
snd_soc_card
*
card
=
runtime
->
card
;
struct
byt_max98090_private
*
drv
=
snd_soc_card_get_drvdata
(
card
);
struct
snd_soc_jack
*
jack
=
&
drv
->
jack
;
card
->
dapm
.
idle_bias_off
=
true
;
ret
=
snd_soc_dai_set_sysclk
(
runtime
->
codec_dai
,
M98090_REG_SYSTEM_CLOCK
,
25000000
,
SND_SOC_CLOCK_IN
);
if
(
ret
<
0
)
{
dev_err
(
card
->
dev
,
"Can't set codec clock %d
\n
"
,
ret
);
return
ret
;
}
/* Enable jack detection */
ret
=
snd_soc_jack_new
(
codec
,
"Headphone"
,
SND_JACK_HEADPHONE
,
jack
);
if
(
ret
)
return
ret
;
ret
=
snd_soc_jack_add_pins
(
jack
,
ARRAY_SIZE
(
hs_jack_pins
),
hs_jack_pins
);
if
(
ret
)
return
ret
;
ret
=
snd_soc_jack_add_gpiods
(
card
->
dev
->
parent
,
jack
,
ARRAY_SIZE
(
hs_jack_gpios
),
hs_jack_gpios
);
if
(
ret
)
return
ret
;
return
max98090_mic_detect
(
codec
,
jack
);
}
static
struct
snd_soc_dai_link
byt_max98090_dais
[]
=
{
{
.
name
=
"Baytrail Audio"
,
.
stream_name
=
"Audio"
,
.
cpu_dai_name
=
"baytrail-pcm-audio"
,
.
codec_dai_name
=
"HiFi"
,
.
codec_name
=
"i2c-193C9890:00"
,
.
platform_name
=
"baytrail-pcm-audio"
,
.
init
=
byt_max98090_init
,
.
dai_fmt
=
SND_SOC_DAIFMT_I2S
|
SND_SOC_DAIFMT_NB_NF
|
SND_SOC_DAIFMT_CBS_CFS
,
},
};
static
struct
snd_soc_card
byt_max98090_card
=
{
.
name
=
"byt-max98090"
,
.
dai_link
=
byt_max98090_dais
,
.
num_links
=
ARRAY_SIZE
(
byt_max98090_dais
),
.
dapm_widgets
=
byt_max98090_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
byt_max98090_widgets
),
.
dapm_routes
=
byt_max98090_audio_map
,
.
num_dapm_routes
=
ARRAY_SIZE
(
byt_max98090_audio_map
),
.
controls
=
byt_max98090_controls
,
.
num_controls
=
ARRAY_SIZE
(
byt_max98090_controls
),
};
static
int
byt_max98090_probe
(
struct
platform_device
*
pdev
)
{
int
ret_val
=
0
;
struct
byt_max98090_private
*
priv
;
priv
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
priv
),
GFP_ATOMIC
);
if
(
!
priv
)
{
dev_err
(
&
pdev
->
dev
,
"allocation failed
\n
"
);
return
-
ENOMEM
;
}
byt_max98090_card
.
dev
=
&
pdev
->
dev
;
snd_soc_card_set_drvdata
(
&
byt_max98090_card
,
priv
);
ret_val
=
devm_snd_soc_register_card
(
&
pdev
->
dev
,
&
byt_max98090_card
);
if
(
ret_val
)
{
dev_err
(
&
pdev
->
dev
,
"snd_soc_register_card failed %d
\n
"
,
ret_val
);
return
ret_val
;
}
return
ret_val
;
}
static
int
byt_max98090_remove
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_card
*
card
=
platform_get_drvdata
(
pdev
);
struct
byt_max98090_private
*
priv
=
snd_soc_card_get_drvdata
(
card
);
snd_soc_jack_free_gpios
(
&
priv
->
jack
,
ARRAY_SIZE
(
hs_jack_gpios
),
hs_jack_gpios
);
return
0
;
}
static
struct
platform_driver
byt_max98090_driver
=
{
.
probe
=
byt_max98090_probe
,
.
remove
=
byt_max98090_remove
,
.
driver
=
{
.
name
=
"byt-max98090"
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
snd_soc_pm_ops
,
},
};
module_platform_driver
(
byt_max98090_driver
)
MODULE_DESCRIPTION
(
"ASoC Intel(R) Baytrail Machine driver"
);
MODULE_AUTHOR
(
"Omair Md Abdullah, Jarkko Nikula"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_ALIAS
(
"platform:byt-max98090"
);
sound/soc/intel/byt-rt5640.c
View file @
9713d5d0
...
...
@@ -132,43 +132,20 @@ static struct snd_soc_card byt_rt5640_card = {
.
num_dapm_routes
=
ARRAY_SIZE
(
byt_rt5640_audio_map
),
};
#ifdef CONFIG_PM_SLEEP
static
const
struct
dev_pm_ops
byt_rt5640_pm_ops
=
{
.
suspend
=
snd_soc_suspend
,
.
resume
=
snd_soc_resume
,
};
#define BYT_RT5640_PM_OPS (&byt_rt5640_pm_ops)
#else
#define BYT_RT5640_PM_OPS NULL
#endif
static
int
byt_rt5640_probe
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_card
*
card
=
&
byt_rt5640_card
;
struct
device
*
dev
=
&
pdev
->
dev
;
card
->
dev
=
&
pdev
->
dev
;
dev_set_drvdata
(
dev
,
card
);
return
snd_soc_register_card
(
card
);
}
static
int
byt_rt5640_remove
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_card
*
card
=
platform_get_drvdata
(
pdev
);
snd_soc_unregister_card
(
card
);
return
0
;
return
devm_snd_soc_register_card
(
&
pdev
->
dev
,
card
);
}
static
struct
platform_driver
byt_rt5640_audio
=
{
.
probe
=
byt_rt5640_probe
,
.
remove
=
byt_rt5640_remove
,
.
driver
=
{
.
name
=
"byt-rt5640"
,
.
owner
=
THIS_MODULE
,
.
pm
=
BYT_RT5640_PM_OPS
,
.
pm
=
&
snd_soc_pm_ops
,
},
};
module_platform_driver
(
byt_rt5640_audio
)
...
...
sound/soc/intel/haswell.c
View file @
9713d5d0
...
...
@@ -202,18 +202,11 @@ static int haswell_audio_probe(struct platform_device *pdev)
{
haswell_rt5640
.
dev
=
&
pdev
->
dev
;
return
snd_soc_register_card
(
&
haswell_rt5640
);
}
static
int
haswell_audio_remove
(
struct
platform_device
*
pdev
)
{
snd_soc_unregister_card
(
&
haswell_rt5640
);
return
0
;
return
devm_snd_soc_register_card
(
&
pdev
->
dev
,
&
haswell_rt5640
);
}
static
struct
platform_driver
haswell_audio
=
{
.
probe
=
haswell_audio_probe
,
.
remove
=
haswell_audio_remove
,
.
driver
=
{
.
name
=
"haswell-audio"
,
.
owner
=
THIS_MODULE
,
...
...
sound/soc/intel/sst-acpi.c
View file @
9713d5d0
...
...
@@ -247,6 +247,7 @@ static struct sst_acpi_desc sst_acpi_broadwell_desc = {
static
struct
sst_acpi_mach
baytrail_machines
[]
=
{
{
"10EC5640"
,
"byt-rt5640"
,
"intel/fw_sst_0f28.bin-i2s_master"
},
{
"193C9890"
,
"byt-max98090"
,
"intel/fw_sst_0f28.bin-i2s_master"
},
{}
};
...
...
sound/soc/intel/sst-baytrail-ipc.c
View file @
9713d5d0
...
...
@@ -22,7 +22,6 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/platform_device.h>
#include <linux/kthread.h>
#include <linux/firmware.h>
...
...
@@ -892,7 +891,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
/* start the IPC message thread */
init_kthread_worker
(
&
byt
->
kworker
);
byt
->
tx_thread
=
kthread_run
(
kthread_worker_fn
,
&
byt
->
kworker
,
&
byt
->
kworker
,
"%s"
,
dev_name
(
byt
->
dev
));
if
(
IS_ERR
(
byt
->
tx_thread
))
{
err
=
PTR_ERR
(
byt
->
tx_thread
);
...
...
@@ -907,7 +906,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
byt
->
dsp
=
sst_dsp_new
(
dev
,
&
byt_dev
,
pdata
);
if
(
byt
->
dsp
==
NULL
)
{
err
=
-
ENODEV
;
goto
err_free_msg
;
goto
dsp_err
;
}
/* keep the DSP in reset state for base FW loading */
...
...
@@ -940,6 +939,8 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
sst_fw_free
(
byt_sst_fw
);
fw_err:
sst_dsp_free
(
byt
->
dsp
);
dsp_err:
kthread_stop
(
byt
->
tx_thread
);
err_free_msg:
kfree
(
byt
->
msg
);
...
...
@@ -954,6 +955,7 @@ void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata)
sst_dsp_reset
(
byt
->
dsp
);
sst_fw_free_all
(
byt
->
dsp
);
sst_dsp_free
(
byt
->
dsp
);
kthread_stop
(
byt
->
tx_thread
);
kfree
(
byt
->
msg
);
}
EXPORT_SYMBOL_GPL
(
sst_byt_dsp_free
);
sound/soc/intel/sst-baytrail-pcm.c
View file @
9713d5d0
...
...
@@ -180,6 +180,7 @@ static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
pcm_data
->
hw_ptr
=
0
;
sst_byt_stream_start
(
byt
,
pcm_data
->
stream
,
0
);
break
;
case
SNDRV_PCM_TRIGGER_RESUME
:
...
...
sound/soc/intel/sst-haswell-ipc.c
View file @
9713d5d0
...
...
@@ -25,7 +25,6 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/list.h>
#include <linux/platform_device.h>
#include <linux/kthread.h>
#include <linux/firmware.h>
...
...
@@ -1730,17 +1729,17 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
ret
=
msg_empty_list_init
(
hsw
);
if
(
ret
<
0
)
goto
list_err
;
return
-
ENOMEM
;
/* start the IPC message thread */
init_kthread_worker
(
&
hsw
->
kworker
);
hsw
->
tx_thread
=
kthread_run
(
kthread_worker_fn
,
&
hsw
->
kworker
,
&
hsw
->
kworker
,
"%s"
,
dev_name
(
hsw
->
dev
));
if
(
IS_ERR
(
hsw
->
tx_thread
))
{
ret
=
PTR_ERR
(
hsw
->
tx_thread
);
dev_err
(
hsw
->
dev
,
"error: failed to create message TX task
\n
"
);
goto
list_err
;
goto
err_free_msg
;
}
init_kthread_work
(
&
hsw
->
kwork
,
ipc_tx_msgs
);
...
...
@@ -1750,7 +1749,7 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
hsw
->
dsp
=
sst_dsp_new
(
dev
,
&
hsw_dev
,
pdata
);
if
(
hsw
->
dsp
==
NULL
)
{
ret
=
-
ENODEV
;
goto
list
_err
;
goto
dsp
_err
;
}
/* keep the DSP in reset state for base FW loading */
...
...
@@ -1794,8 +1793,11 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
sst_fw_free
(
hsw_sst_fw
);
fw_err:
sst_dsp_free
(
hsw
->
dsp
);
dsp_err:
kthread_stop
(
hsw
->
tx_thread
);
err_free_msg:
kfree
(
hsw
->
msg
);
list_err:
return
ret
;
}
EXPORT_SYMBOL_GPL
(
sst_hsw_dsp_init
);
...
...
@@ -1808,6 +1810,7 @@ void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata)
sst_fw_free_all
(
hsw
->
dsp
);
sst_dsp_free
(
hsw
->
dsp
);
kfree
(
hsw
->
scratch
);
kthread_stop
(
hsw
->
tx_thread
);
kfree
(
hsw
->
msg
);
}
EXPORT_SYMBOL_GPL
(
sst_hsw_dsp_free
);
sound/soc/intel/sst-haswell-pcm.c
View file @
9713d5d0
...
...
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <asm/page.h>
#include <asm/pgtable.h>
...
...
sound/soc/soc-jack.c
View file @
9713d5d0
...
...
@@ -14,6 +14,7 @@
#include <sound/jack.h>
#include <sound/soc.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
...
...
@@ -240,7 +241,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
int
enable
;
int
report
;
enable
=
gpio
_get_value_cansleep
(
gpio
->
gpio
);
enable
=
gpio
d_get_value_cansleep
(
gpio
->
desc
);
if
(
gpio
->
invert
)
enable
=
!
enable
;
...
...
@@ -297,31 +298,50 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
int
i
,
ret
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
!
gpio_is_valid
(
gpios
[
i
].
gpio
))
{
dev_err
(
jack
->
codec
->
dev
,
"ASoC: Invalid gpio %d
\n
"
,
gpios
[
i
].
gpio
);
ret
=
-
EINVAL
;
goto
undo
;
}
if
(
!
gpios
[
i
].
name
)
{
dev_err
(
jack
->
codec
->
dev
,
"ASoC: No name for gpio %d
\n
"
,
gpios
[
i
].
gpio
);
dev_err
(
jack
->
codec
->
dev
,
"ASoC: No name for gpio at index %d
\n
"
,
i
);
ret
=
-
EINVAL
;
goto
undo
;
}
ret
=
gpio_request
(
gpios
[
i
].
gpio
,
gpios
[
i
].
name
);
if
(
ret
)
goto
undo
;
if
(
gpios
[
i
].
gpiod_dev
)
{
/* GPIO descriptor */
gpios
[
i
].
desc
=
gpiod_get_index
(
gpios
[
i
].
gpiod_dev
,
gpios
[
i
].
name
,
gpios
[
i
].
idx
);
if
(
IS_ERR
(
gpios
[
i
].
desc
))
{
ret
=
PTR_ERR
(
gpios
[
i
].
desc
);
dev_err
(
gpios
[
i
].
gpiod_dev
,
"ASoC: Cannot get gpio at index %d: %d"
,
i
,
ret
);
goto
undo
;
}
}
else
{
/* legacy GPIO number */
if
(
!
gpio_is_valid
(
gpios
[
i
].
gpio
))
{
dev_err
(
jack
->
codec
->
dev
,
"ASoC: Invalid gpio %d
\n
"
,
gpios
[
i
].
gpio
);
ret
=
-
EINVAL
;
goto
undo
;
}
ret
=
gpio_request
(
gpios
[
i
].
gpio
,
gpios
[
i
].
name
);
if
(
ret
)
goto
undo
;
gpios
[
i
].
desc
=
gpio_to_desc
(
gpios
[
i
].
gpio
);
}
ret
=
gpio
_direction_input
(
gpios
[
i
].
gpio
);
ret
=
gpio
d_direction_input
(
gpios
[
i
].
desc
);
if
(
ret
)
goto
err
;
INIT_DELAYED_WORK
(
&
gpios
[
i
].
work
,
gpio_work
);
gpios
[
i
].
jack
=
jack
;
ret
=
request_any_context_irq
(
gpio
_to_irq
(
gpios
[
i
].
gpio
),
ret
=
request_any_context_irq
(
gpio
d_to_irq
(
gpios
[
i
].
desc
),
gpio_handler
,
IRQF_TRIGGER_RISING
|
IRQF_TRIGGER_FALLING
,
...
...
@@ -331,15 +351,15 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
goto
err
;
if
(
gpios
[
i
].
wake
)
{
ret
=
irq_set_irq_wake
(
gpio
_to_irq
(
gpios
[
i
].
gpio
),
1
);
ret
=
irq_set_irq_wake
(
gpio
d_to_irq
(
gpios
[
i
].
desc
),
1
);
if
(
ret
!=
0
)
dev_err
(
jack
->
codec
->
dev
,
"ASoC: "
"Failed to mark GPIO
%d as wake source: %d
\n
"
,
gpios
[
i
].
gpio
,
ret
);
dev_err
(
jack
->
codec
->
dev
,
"ASoC: Failed to mark GPIO at index
%d as wake source: %d
\n
"
,
i
,
ret
);
}
/* Expose GPIO value over sysfs for diagnostic purposes */
gpio
_export
(
gpios
[
i
].
gpio
,
false
);
gpio
d_export
(
gpios
[
i
].
desc
,
false
);
/* Update initial jack status */
schedule_delayed_work
(
&
gpios
[
i
].
work
,
...
...
@@ -357,6 +377,30 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
}
EXPORT_SYMBOL_GPL
(
snd_soc_jack_add_gpios
);
/**
* snd_soc_jack_add_gpiods - Associate GPIO descriptor pins with an ASoC jack
*
* @gpiod_dev: GPIO consumer device
* @jack: ASoC jack
* @count: number of pins
* @gpios: array of gpio pins
*
* This function will request gpio, set data direction and request irq
* for each gpio in the array.
*/
int
snd_soc_jack_add_gpiods
(
struct
device
*
gpiod_dev
,
struct
snd_soc_jack
*
jack
,
int
count
,
struct
snd_soc_jack_gpio
*
gpios
)
{
int
i
;
for
(
i
=
0
;
i
<
count
;
i
++
)
gpios
[
i
].
gpiod_dev
=
gpiod_dev
;
return
snd_soc_jack_add_gpios
(
jack
,
count
,
gpios
);
}
EXPORT_SYMBOL_GPL
(
snd_soc_jack_add_gpiods
);
/**
* snd_soc_jack_free_gpios - Release GPIO pins' resources of an ASoC jack
*
...
...
@@ -372,10 +416,10 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
int
i
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
gpio
_unexport
(
gpios
[
i
].
gpio
);
free_irq
(
gpio
_to_irq
(
gpios
[
i
].
gpio
),
&
gpios
[
i
]);
gpio
d_unexport
(
gpios
[
i
].
desc
);
free_irq
(
gpio
d_to_irq
(
gpios
[
i
].
desc
),
&
gpios
[
i
]);
cancel_delayed_work_sync
(
&
gpios
[
i
].
work
);
gpio
_free
(
gpios
[
i
].
gpio
);
gpio
d_put
(
gpios
[
i
].
desc
);
gpios
[
i
].
jack
=
NULL
;
}
}
...
...
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