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
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
Show 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,14 +298,30 @@ 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
);
if
(
!
gpio
s
[
i
].
name
)
{
dev_err
(
jack
->
codec
->
dev
,
"ASoC: No name for gpio at index %d
\n
"
,
i
);
ret
=
-
EINVAL
;
goto
undo
;
}
if
(
!
gpios
[
i
].
name
)
{
dev_err
(
jack
->
codec
->
dev
,
"ASoC: No name for gpio %d
\n
"
,
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
;
...
...
@@ -314,14 +331,17 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
if
(
ret
)
goto
undo
;
ret
=
gpio_direction_input
(
gpios
[
i
].
gpio
);
gpios
[
i
].
desc
=
gpio_to_desc
(
gpios
[
i
].
gpio
);
}
ret
=
gpiod_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