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
d67a39ab
Commit
d67a39ab
authored
May 26, 2015
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
greybus: Merge branch 'master' of github.com:gregkh/greybus
parents
d52b35f6
30c6d9d7
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
681 additions
and
141 deletions
+681
-141
drivers/staging/greybus/Makefile
drivers/staging/greybus/Makefile
+2
-0
drivers/staging/greybus/audio-dai.c
drivers/staging/greybus/audio-dai.c
+10
-1
drivers/staging/greybus/audio-gb-cmds.c
drivers/staging/greybus/audio-gb-cmds.c
+62
-53
drivers/staging/greybus/audio-pcm.c
drivers/staging/greybus/audio-pcm.c
+47
-3
drivers/staging/greybus/audio.c
drivers/staging/greybus/audio.c
+56
-15
drivers/staging/greybus/audio.h
drivers/staging/greybus/audio.h
+21
-6
drivers/staging/greybus/core.c
drivers/staging/greybus/core.c
+18
-10
drivers/staging/greybus/endo.c
drivers/staging/greybus/endo.c
+79
-32
drivers/staging/greybus/endo.h
drivers/staging/greybus/endo.h
+7
-4
drivers/staging/greybus/es1.c
drivers/staging/greybus/es1.c
+18
-5
drivers/staging/greybus/es2.c
drivers/staging/greybus/es2.c
+15
-2
drivers/staging/greybus/gpio.c
drivers/staging/greybus/gpio.c
+0
-1
drivers/staging/greybus/greybus.h
drivers/staging/greybus/greybus.h
+6
-2
drivers/staging/greybus/greybus_manifest.h
drivers/staging/greybus/greybus_manifest.h
+3
-2
drivers/staging/greybus/greybus_protocols.h
drivers/staging/greybus/greybus_protocols.h
+57
-0
drivers/staging/greybus/i2c.c
drivers/staging/greybus/i2c.c
+0
-2
drivers/staging/greybus/protocol.h
drivers/staging/greybus/protocol.h
+1
-1
drivers/staging/greybus/pwm.c
drivers/staging/greybus/pwm.c
+1
-1
drivers/staging/greybus/spi.c
drivers/staging/greybus/spi.c
+0
-1
drivers/staging/greybus/svc.c
drivers/staging/greybus/svc.c
+256
-0
drivers/staging/greybus/svc.h
drivers/staging/greybus/svc.h
+22
-0
No files found.
drivers/staging/greybus/Makefile
View file @
d67a39ab
...
...
@@ -25,6 +25,7 @@ gb-phy-y := gpbridge.o \
audio-gb-cmds.o
# Prefix all modules with gb-
gb-svc-y
:=
svc.o
gb-vibrator-y
:=
vibrator.o
gb-battery-y
:=
battery.o
gb-loopback-y
:=
loopback.o
...
...
@@ -33,6 +34,7 @@ gb-es1-y := es1.o
gb-es2-y
:=
es2.o
obj-m
+=
greybus.o
obj-m
+=
gb-svc.o
obj-m
+=
gb-phy.o
obj-m
+=
gb-vibrator.o
obj-m
+=
gb-battery.o
...
...
drivers/staging/greybus/audio-dai.c
View file @
d67a39ab
/*
* Greybus audio Digital Audio Interface (DAI) driver
*
* Copyright 2015 Google Inc.
* Copyright 2015 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/interrupt.h>
...
...
@@ -11,8 +20,8 @@
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include <sound/simple_card.h>
#include "greybus.h"
#include "gpbridge.h"
#include "audio.h"
/*
...
...
drivers/staging/greybus/audio-gb-cmds.c
View file @
d67a39ab
/*
* Greybus audio commands
*
* Copyright 2015 Google Inc.
* Copyright 2015 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
#include <linux/kernel.h>
#include "greybus.h"
#include "gpbridge.h"
#include "audio.h"
#define GB_I2S_MGMT_VERSION_MAJOR 0x00
...
...
@@ -89,21 +98,12 @@ int gb_i2s_mgmt_set_samples_per_message(
&
request
,
sizeof
(
request
),
NULL
,
0
);
}
/*
* XXX This is sort of a generic "setup" function which probably needs
* to be broken up, and tied into the constraints.
*
* I'm on the fence if we should just dictate that we only support
* 48k, 16bit, 2 channel, and avoid doign the whole probe for configurations
* and then picking one.
*/
int
gb_i2s_mgmt_setup
(
struct
gb_connection
*
connection
)
int
gb_i2s_mgmt_get_cfgs
(
struct
gb_snd
*
snd_dev
,
struct
gb_connection
*
connection
)
{
struct
gb_i2s_mgmt_get_supported_configurations_response
*
get_cfg
;
struct
gb_i2s_mgmt_set_configuration_request
set_cfg
;
struct
gb_i2s_mgmt_configuration
*
cfg
;
size_t
size
;
int
i
,
ret
;
int
ret
;
size
=
sizeof
(
*
get_cfg
)
+
(
CONFIG_COUNT_MAX
*
sizeof
(
get_cfg
->
config
[
0
]));
...
...
@@ -116,70 +116,79 @@ int gb_i2s_mgmt_setup(struct gb_connection *connection)
size
);
if
(
ret
)
{
pr_err
(
"get_supported_config failed: %d
\n
"
,
ret
);
goto
free_get_cfg
;
goto
err_free_get_cfg
;
}
snd_dev
->
i2s_configs
=
get_cfg
;
return
0
;
err_free_get_cfg:
kfree
(
get_cfg
);
return
ret
;
}
void
gb_i2s_mgmt_free_cfgs
(
struct
gb_snd
*
snd_dev
)
{
kfree
(
snd_dev
->
i2s_configs
);
snd_dev
->
i2s_configs
=
NULL
;
}
int
gb_i2s_mgmt_set_cfg
(
struct
gb_snd
*
snd_dev
,
int
rate
,
int
chans
,
int
bytes_per_chan
,
int
is_le
)
{
struct
gb_i2s_mgmt_set_configuration_request
set_cfg
;
struct
gb_i2s_mgmt_configuration
*
cfg
;
int
i
,
ret
;
u8
byte_order
=
GB_I2S_MGMT_BYTE_ORDER_NA
;
if
(
bytes_per_chan
>
1
)
{
if
(
is_le
)
byte_order
=
GB_I2S_MGMT_BYTE_ORDER_LE
;
else
byte_order
=
GB_I2S_MGMT_BYTE_ORDER_BE
;
}
/* Pick 48KHz 16-bits/channel */
for
(
i
=
0
,
cfg
=
get_cfg
->
config
;
i
<
CONFIG_COUNT_MAX
;
i
++
,
cfg
++
)
{
if
((
le32_to_cpu
(
cfg
->
sample_frequency
)
==
GB_SAMPLE_RATE
)
&&
(
cfg
->
num_channels
==
2
)
&&
(
cfg
->
bytes_per_channel
==
2
)
&&
(
cfg
->
byte_order
&
GB_I2S_MGMT_BYTE_ORDER_LE
)
&&
(
le32_to_cpu
(
cfg
->
spatial_locations
)
==
(
GB_I2S_MGMT_SPATIAL_LOCATION_FL
|
GB_I2S_MGMT_SPATIAL_LOCATION_FR
))
&&
(
le32_to_cpu
(
cfg
->
ll_protocol
)
&
GB_I2S_MGMT_PROTOCOL_I2S
)
&&
for
(
i
=
0
,
cfg
=
snd_dev
->
i2s_configs
->
config
;
i
<
CONFIG_COUNT_MAX
;
i
++
,
cfg
++
)
{
if
((
cfg
->
sample_frequency
==
cpu_to_le32
(
rate
))
&&
(
cfg
->
num_channels
==
chans
)
&&
(
cfg
->
bytes_per_channel
==
bytes_per_chan
)
&&
(
cfg
->
byte_order
&
byte_order
)
&&
(
cfg
->
ll_protocol
&
cpu_to_le32
(
GB_I2S_MGMT_PROTOCOL_I2S
))
&&
(
cfg
->
ll_mclk_role
&
GB_I2S_MGMT_ROLE_MASTER
)
&&
(
cfg
->
ll_bclk_role
&
GB_I2S_MGMT_ROLE_MASTER
)
&&
(
cfg
->
ll_wclk_role
&
GB_I2S_MGMT_ROLE_MASTER
)
&&
(
cfg
->
ll_wclk_polarity
&
GB_I2S_MGMT_POLARITY_NORMAL
)
&&
(
cfg
->
ll_wclk_change_edge
&
GB_I2S_MGMT_EDGE_FALLING
)
&&
(
cfg
->
ll_wclk_tx_edge
&
GB_I2S_MGMT_EDGE_
FALL
ING
)
&&
(
cfg
->
ll_wclk_rx_edge
&
GB_I2S_MGMT_EDGE_
RIS
ING
)
&&
(
cfg
->
ll_wclk_tx_edge
&
GB_I2S_MGMT_EDGE_
RIS
ING
)
&&
(
cfg
->
ll_wclk_rx_edge
&
GB_I2S_MGMT_EDGE_
FALL
ING
)
&&
(
cfg
->
ll_data_offset
==
1
))
break
;
}
if
(
i
>=
CONFIG_COUNT_MAX
)
{
pr_err
(
"No valid configuration
\n
"
);
ret
=
-
EINVAL
;
goto
free_get_cfg
;
return
-
EINVAL
;
}
memcpy
(
&
set_cfg
,
cfg
,
sizeof
(
set_cfg
));
set_cfg
.
config
.
byte_order
=
GB_I2S_MGMT_BYTE_ORDER_LE
;
set_cfg
.
config
.
byte_order
=
byte_order
;
set_cfg
.
config
.
ll_protocol
=
cpu_to_le32
(
GB_I2S_MGMT_PROTOCOL_I2S
);
set_cfg
.
config
.
ll_mclk_role
=
GB_I2S_MGMT_ROLE_MASTER
;
set_cfg
.
config
.
ll_bclk_role
=
GB_I2S_MGMT_ROLE_MASTER
;
set_cfg
.
config
.
ll_wclk_role
=
GB_I2S_MGMT_ROLE_MASTER
;
set_cfg
.
config
.
ll_wclk_polarity
=
GB_I2S_MGMT_POLARITY_NORMAL
;
set_cfg
.
config
.
ll_wclk_change_edge
=
GB_I2S_MGMT_EDGE_
RIS
ING
;
set_cfg
.
config
.
ll_wclk_tx_edge
=
GB_I2S_MGMT_EDGE_
FALL
ING
;
set_cfg
.
config
.
ll_wclk_rx_edge
=
GB_I2S_MGMT_EDGE_
RIS
ING
;
set_cfg
.
config
.
ll_wclk_change_edge
=
GB_I2S_MGMT_EDGE_
FALL
ING
;
set_cfg
.
config
.
ll_wclk_tx_edge
=
GB_I2S_MGMT_EDGE_
RIS
ING
;
set_cfg
.
config
.
ll_wclk_rx_edge
=
GB_I2S_MGMT_EDGE_
FALL
ING
;
ret
=
gb_i2s_mgmt_set_configuration
(
connection
,
&
set_cfg
);
if
(
ret
)
{
ret
=
gb_i2s_mgmt_set_configuration
(
snd_dev
->
mgmt_
connection
,
&
set_cfg
);
if
(
ret
)
pr_err
(
"set_configuration failed: %d
\n
"
,
ret
);
goto
free_get_cfg
;
}
ret
=
gb_i2s_mgmt_set_samples_per_message
(
connection
,
CONFIG_SAMPLES_PER_MSG
);
if
(
ret
)
{
pr_err
(
"set_samples_per_msg failed: %d
\n
"
,
ret
);
goto
free_get_cfg
;
}
/* XXX Add start delay here (probably 1ms) */
ret
=
gb_i2s_mgmt_activate_cport
(
connection
,
CONFIG_I2S_REMOTE_DATA_CPORT
);
if
(
ret
)
{
pr_err
(
"activate_cport failed: %d
\n
"
,
ret
);
goto
free_get_cfg
;
}
free_get_cfg:
kfree
(
get_cfg
);
return
ret
;
}
...
...
drivers/staging/greybus/audio-pcm.c
View file @
d67a39ab
/*
* Greybus audio Pulse Code Modulation (PCM) driver
*
* Copyright 2015 Google Inc.
* Copyright 2015 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/interrupt.h>
...
...
@@ -11,8 +20,8 @@
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include <sound/simple_card.h>
#include "greybus.h"
#include "gpbridge.h"
#include "audio.h"
/*
...
...
@@ -32,15 +41,33 @@ static void gb_pcm_work(struct work_struct *work)
struct
snd_pcm_substream
*
substream
=
snd_dev
->
substream
;
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
unsigned
int
stride
,
frames
,
oldptr
;
int
period_elapsed
;
int
period_elapsed
,
ret
;
char
*
address
;
long
len
;
if
(
!
snd_dev
)
return
;
if
(
!
atomic_read
(
&
snd_dev
->
running
))
if
(
!
atomic_read
(
&
snd_dev
->
running
))
{
if
(
snd_dev
->
cport_active
)
{
ret
=
gb_i2s_mgmt_deactivate_cport
(
snd_dev
->
mgmt_connection
,
snd_dev
->
i2s_tx_connection
->
bundle_cport_id
);
if
(
ret
)
/* XXX Do what else with failure? */
pr_err
(
"deactivate_cport failed: %d
\n
"
,
ret
);
snd_dev
->
cport_active
=
false
;
}
return
;
}
else
if
(
!
snd_dev
->
cport_active
)
{
ret
=
gb_i2s_mgmt_activate_cport
(
snd_dev
->
mgmt_connection
,
snd_dev
->
i2s_tx_connection
->
bundle_cport_id
);
if
(
ret
)
pr_err
(
"activate_cport failed: %d
\n
"
,
ret
);
snd_dev
->
cport_active
=
true
;
}
address
=
runtime
->
dma_area
+
snd_dev
->
hwptr_done
;
...
...
@@ -88,6 +115,7 @@ static enum hrtimer_restart gb_pcm_timer_function(struct hrtimer *hrtimer)
void
gb_pcm_hrtimer_start
(
struct
gb_snd
*
snd_dev
)
{
atomic_set
(
&
snd_dev
->
running
,
1
);
queue_work
(
snd_dev
->
workqueue
,
&
snd_dev
->
work
);
/* Activates CPort */
hrtimer_start
(
&
snd_dev
->
timer
,
ns_to_ktime
(
CONFIG_PERIOD_NS
),
HRTIMER_MODE_REL
);
}
...
...
@@ -96,6 +124,7 @@ void gb_pcm_hrtimer_stop(struct gb_snd *snd_dev)
{
atomic_set
(
&
snd_dev
->
running
,
0
);
hrtimer_cancel
(
&
snd_dev
->
timer
);
queue_work
(
snd_dev
->
workqueue
,
&
snd_dev
->
work
);
/* Deactivates CPort */
}
static
int
gb_pcm_hrtimer_init
(
struct
gb_snd
*
snd_dev
)
...
...
@@ -200,6 +229,21 @@ static int gb_pcm_close(struct snd_pcm_substream *substream)
static
int
gb_pcm_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
hw_params
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
gb_snd
*
snd_dev
;
int
rate
,
chans
,
bytes_per_chan
,
is_le
,
ret
;
snd_dev
=
snd_soc_dai_get_drvdata
(
rtd
->
cpu_dai
);
rate
=
params_rate
(
hw_params
);
chans
=
params_channels
(
hw_params
);
bytes_per_chan
=
snd_pcm_format_width
(
params_format
(
hw_params
))
/
8
;
is_le
=
snd_pcm_format_little_endian
(
params_format
(
hw_params
));
ret
=
gb_i2s_mgmt_set_cfg
(
snd_dev
,
rate
,
chans
,
bytes_per_chan
,
is_le
);
if
(
ret
)
return
ret
;
return
snd_pcm_lib_malloc_pages
(
substream
,
params_buffer_bytes
(
hw_params
));
}
...
...
drivers/staging/greybus/audio.c
View file @
d67a39ab
/*
* Greybus audio driver
*
* Copyright 2015 Google Inc.
* Copyright 2015 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/i2c.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include <sound/simple_card.h>
#include "greybus.h"
#include "gpbridge.h"
#include "audio.h"
#define GB_AUDIO_DATA_DRIVER_NAME "gb_audio_data"
#define GB_AUDIO_MGMT_DRIVER_NAME "gb_audio_mgmt"
#define RT5647_I2C_ADAPTER_NR 6
#define RT5647_I2C_ADDR 0x1b
/*
* gb_snd management functions
*/
...
...
@@ -107,13 +118,17 @@ static struct asoc_simple_card_info *setup_card_info(int device_count)
obj
->
card_info
.
platform
=
obj
->
platform_name
;
obj
->
card_info
.
cpu_dai
.
name
=
obj
->
dai_name
;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
obj
->
card_info
.
cpu_dai
.
fmt
=
GB_FMTS
;
obj
->
card_info
.
cpu_dai
.
fmt
=
SND_SOC_DAIFMT_CBM_CFM
;
#endif
#if USE_RT5645
obj
->
card_info
.
daifmt
=
GB_FMTS
;
sprintf
(
obj
->
codec_name
,
"rt5645.%s"
,
"6-001b"
);
/* XXX do i2c bus addr dynamically */
obj
->
card_info
.
daifmt
=
SND_SOC_DAIFMT_NB_NF
|
SND_SOC_DAIFMT_I2S
;
sprintf
(
obj
->
codec_name
,
"rt5645.%d-%04x"
,
RT5647_I2C_ADAPTER_NR
,
RT5647_I2C_ADDR
);
obj
->
card_info
.
codec_dai
.
name
=
"rt5645-aif1"
;
obj
->
card_info
.
codec_dai
.
fmt
=
SND_SOC_DAIFMT_CBM_CFM
;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
obj
->
card_info
.
codec_dai
.
fmt
=
SND_SOC_DAIFMT_CBS_CFS
;
#endif
obj
->
card_info
.
codec_dai
.
sysclk
=
12288000
;
#else
sprintf
(
obj
->
codec_name
,
"spdif-dit"
);
...
...
@@ -150,6 +165,9 @@ static int gb_i2s_transmitter_connection_init(struct gb_connection *connection)
struct
gb_snd
*
snd_dev
;
struct
platform_device
*
codec
,
*
dai
;
struct
asoc_simple_card_info
*
simple_card
;
#if USE_RT5645
struct
i2c_board_info
rt5647_info
;
#endif
unsigned
long
flags
;
int
ret
;
...
...
@@ -212,6 +230,18 @@ static int gb_i2s_transmitter_connection_init(struct gb_connection *connection)
goto
out_get_ver
;
}
#if USE_RT5645
rt5647_info
.
addr
=
RT5647_I2C_ADDR
;
strlcpy
(
rt5647_info
.
type
,
"rt5647"
,
I2C_NAME_SIZE
);
snd_dev
->
rt5647
=
i2c_new_device
(
i2c_get_adapter
(
RT5647_I2C_ADAPTER_NR
),
&
rt5647_info
);
if
(
!
snd_dev
->
rt5647
)
{
pr_err
(
"can't create rt5647 i2c device
\n
"
);
goto
out_get_ver
;
}
#endif
return
0
;
out_get_ver:
...
...
@@ -231,6 +261,10 @@ static void gb_i2s_transmitter_connection_exit(struct gb_connection *connection)
snd_dev
=
(
struct
gb_snd
*
)
connection
->
private
;
#if USE_RT5645
i2c_unregister_device
(
snd_dev
->
rt5647
);
#endif
platform_device_unregister
(
&
snd_dev
->
card
);
platform_device_unregister
(
&
snd_dev
->
cpu_dai
);
platform_device_unregister
(
snd_dev
->
codec
);
...
...
@@ -261,19 +295,30 @@ static int gb_i2s_mgmt_connection_init(struct gb_connection *connection)
goto
err_free_snd_dev
;
}
gb_i2s_mgmt_setup
(
connection
);
ret
=
gb_i2s_mgmt_get_cfgs
(
snd_dev
,
connection
);
if
(
ret
)
{
pr_err
(
"can't get i2s configurations: %d
\n
"
,
ret
);
goto
err_free_snd_dev
;
}
ret
=
gb_i2s_mgmt_set_samples_per_message
(
snd_dev
->
mgmt_connection
,
CONFIG_SAMPLES_PER_MSG
);
if
(
ret
)
{
pr_err
(
"set_samples_per_msg failed: %d
\n
"
,
ret
);
goto
err_free_i2s_configs
;
}
snd_dev
->
send_data_req_buf
=
kzalloc
(
SEND_DATA_BUF_LEN
,
GFP_KERNEL
);
if
(
!
snd_dev
->
send_data_req_buf
)
{
ret
=
-
ENOMEM
;
goto
err_
deactivate_cport
;
goto
err_
free_i2s_configs
;
}
return
0
;
err_
deactivate_cport
:
gb_i2s_mgmt_
deactivate_cport
(
connection
,
CONFIG_I2S_REMOTE_DATA_CPORT
);
err_
free_i2s_configs
:
gb_i2s_mgmt_
free_cfgs
(
snd_dev
);
err_free_snd_dev:
gb_free_snd
(
snd_dev
);
return
ret
;
...
...
@@ -282,12 +327,8 @@ static int gb_i2s_mgmt_connection_init(struct gb_connection *connection)
static
void
gb_i2s_mgmt_connection_exit
(
struct
gb_connection
*
connection
)
{
struct
gb_snd
*
snd_dev
=
(
struct
gb_snd
*
)
connection
->
private
;
int
ret
;
ret
=
gb_i2s_mgmt_deactivate_cport
(
connection
,
CONFIG_I2S_REMOTE_DATA_CPORT
);
if
(
ret
)
pr_err
(
"deactivate_cport failed: %d
\n
"
,
ret
);
gb_i2s_mgmt_free_cfgs
(
snd_dev
);
kfree
(
snd_dev
->
send_data_req_buf
);
snd_dev
->
send_data_req_buf
=
NULL
;
...
...
drivers/staging/greybus/audio.h
View file @
d67a39ab
/*
* Greybus audio
*
* Copyright 2015 Google Inc.
* Copyright 2015 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
#ifndef __GB_AUDIO_H
#define __GB_AUDIO_H
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <sound/soc.h>
#include "greybus.h"
#include "gpbridge.h"
#include "greybus.h"
#define GB_SAMPLE_RATE 48000
#define GB_RATES SNDRV_PCM_RATE_48000
...
...
@@ -20,9 +29,7 @@
#define CONFIG_SAMPLES_PER_MSG 48L
#define CONFIG_PERIOD_NS 1000000
/* send msg every 1ms */
#define CONFIG_COUNT_MAX 32
#define CONFIG_I2S_REMOTE_DATA_CPORT 7
/* XXX shouldn't be hardcoded...*/
#define RT5647_SLAVE_ADDR 0x1b
/* from toshiba/quanta code */
#define CONFIG_COUNT_MAX 20
/* Switch between dummy spdif and jetson rt5645 codec */
#define USE_RT5645 0
...
...
@@ -42,9 +49,12 @@ struct gb_snd {
struct
platform_device
cpu_dai
;
struct
platform_device
*
codec
;
struct
asoc_simple_card_info
*
simple_card_info
;
struct
i2c_client
*
rt5647
;
struct
gb_connection
*
mgmt_connection
;
struct
gb_connection
*
i2s_tx_connection
;
struct
gb_connection
*
i2s_rx_connection
;
struct
gb_i2s_mgmt_get_supported_configurations_response
*
i2s_configs
;
char
*
send_data_req_buf
;
long
send_data_sample_count
;
int
gb_bundle_id
;
...
...
@@ -52,6 +62,7 @@ struct gb_snd {
struct
snd_pcm_substream
*
substream
;
struct
hrtimer
timer
;
atomic_t
running
;
bool
cport_active
;
struct
workqueue_struct
*
workqueue
;
struct
work_struct
work
;
int
hwptr_done
;
...
...
@@ -78,7 +89,11 @@ int gb_i2s_mgmt_set_configuration(struct gb_connection *connection,
struct
gb_i2s_mgmt_set_configuration_request
*
set_cfg
);
int
gb_i2s_mgmt_set_samples_per_message
(
struct
gb_connection
*
connection
,
uint16_t
samples_per_message
);
int
gb_i2s_mgmt_setup
(
struct
gb_connection
*
connection
);
int
gb_i2s_mgmt_get_cfgs
(
struct
gb_snd
*
snd_dev
,
struct
gb_connection
*
connection
);
void
gb_i2s_mgmt_free_cfgs
(
struct
gb_snd
*
snd_dev
);
int
gb_i2s_mgmt_set_cfg
(
struct
gb_snd
*
snd_dev
,
int
rate
,
int
chans
,
int
bytes_per_chan
,
int
is_le
);
int
gb_i2s_send_data
(
struct
gb_connection
*
connection
,
void
*
req_buf
,
void
*
source_addr
,
size_t
len
,
int
sample_num
);
...
...
drivers/staging/greybus/core.c
View file @
d67a39ab
/*
* Greybus "Core"
*
* Copyright 2014 Google Inc.
* Copyright 2014 Linaro Ltd.
* Copyright 2014
-2015
Google Inc.
* Copyright 2014
-2015
Linaro Ltd.
*
* Released under the GPLv2 only.
*/
...
...
@@ -185,7 +185,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
if
((
!
driver
->
message_send
)
||
(
!
driver
->
message_cancel
)
||
(
!
driver
->
submit_svc
))
{
pr_err
(
"Must implement all greybus_host_driver callbacks!
\n
"
);
return
NULL
;
return
ERR_PTR
(
-
EINVAL
)
;
}
if
(
buffer_size_max
<
GB_OPERATION_MESSAGE_SIZE_MIN
)
{
...
...
@@ -205,7 +205,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
hd
=
kzalloc
(
sizeof
(
*
hd
)
+
driver
->
hd_priv_size
,
GFP_KERNEL
);
if
(
!
hd
)
return
NULL
;
return
ERR_PTR
(
-
ENOMEM
)
;
kref_init
(
&
hd
->
kref
);
hd
->
parent
=
parent
;
...
...
@@ -215,16 +215,24 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
ida_init
(
&
hd
->
cport_id_map
);
hd
->
buffer_size_max
=
buffer_size_max
;
hd
->
endo
=
gb_endo_create
(
hd
);
if
(
!
hd
->
endo
)
{
greybus_remove_hd
(
hd
);
return
NULL
;
}
return
hd
;
}
EXPORT_SYMBOL_GPL
(
greybus_create_hd
);
int
greybus_endo_setup
(
struct
greybus_host_device
*
hd
,
u16
endo_id
,
u8
ap_intf_id
)
{
struct
gb_endo
*
endo
;
endo
=
gb_endo_create
(
hd
,
endo_id
,
ap_intf_id
);
if
(
IS_ERR
(
endo
))
return
PTR_ERR
(
endo
);
hd
->
endo
=
endo
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
greybus_endo_setup
);
void
greybus_remove_hd
(
struct
greybus_host_device
*
hd
)
{
/*
...
...
drivers/staging/greybus/endo.c
View file @
d67a39ab
/*
* Greybus endo code
*
* Copyright 2015 Google Inc.
* Copyright 2014 Linaro Ltd.
* Copyright 201
4-201
5 Google Inc.
* Copyright 2014
-2015
Linaro Ltd.
*
* Released under the GPLv2 only.
*/
...
...
@@ -29,36 +29,82 @@
#define endo_back_left_ribs(id, ribs) (((id) >> (ribs)) & ENDO_BACK_SIDE_RIBS_MASK(ribs))
#define endo_back_right_ribs(id, ribs) ((id) & ENDO_BACK_SIDE_RIBS_MASK(ribs))
/*
* An Endo has interface block positions on the front and back.
* Each has numeric ID, starting with 1 (interface 0 represents
* the SVC within the Endo itself). The maximum interface ID is the
* also the number of non-SVC interfaces possible on the endo.
*
* Total number of interfaces:
* - Front: 4
* - Back left: max_ribs + 1
* - Back right: max_ribs + 1
*/
#define max_endo_interface_id(endo_layout) \
(4 + ((endo_layout)->max_ribs + 1) * 2)
/* endo sysfs attributes */
static
ssize_t
serial_number_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
static
ssize_t
svc_serial_number_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
gb_endo
*
endo
=
to_gb_endo
(
dev
);
return
sprintf
(
buf
,
"%s"
,
&
endo
->
svc_info
.
serial_number
[
0
]);
}
static
DEVICE_ATTR_RO
(
svc_serial_number
);
static
ssize_t
svc_version_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
gb_endo
*
endo
=
to_gb_endo
(
dev
);
return
sprintf
(
buf
,
"%s"
,
&
endo
->
svc
.
serial_number
[
0
]);
return
sprintf
(
buf
,
"%s"
,
&
endo
->
svc
_info
.
version
[
0
]);
}
static
DEVICE_ATTR_RO
(
serial_number
);
static
DEVICE_ATTR_RO
(
svc_version
);
static
struct
attribute
*
svc_attrs
[]
=
{
&
dev_attr_svc_serial_number
.
attr
,
&
dev_attr_svc_version
.
attr
,
NULL
,
};
static
ssize_t
version_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
static
const
struct
attribute_group
svc_group
=
{
.
attrs
=
svc_attrs
,
.
name
=
"SVC"
,
};
static
ssize_t
endo_id_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
gb_endo
*
endo
=
to_gb_endo
(
dev
);
return
sprintf
(
buf
,
"
%s"
,
&
endo
->
svc
.
version
[
0
]
);
return
sprintf
(
buf
,
"
0x%04x"
,
endo
->
id
);
}
static
DEVICE_ATTR_RO
(
version
);
static
DEVICE_ATTR_RO
(
endo_id
);
static
ssize_t
ap_intf_id_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
gb_endo
*
endo
=
to_gb_endo
(
dev
);
return
sprintf
(
buf
,
"0x%02x"
,
endo
->
ap_intf_id
);
}
static
DEVICE_ATTR_RO
(
ap_intf_id
);
static
struct
attribute
*
endo_attrs
[]
=
{
&
dev_attr_
serial_number
.
attr
,
&
dev_attr_
version
.
attr
,
&
dev_attr_
endo_id
.
attr
,
&
dev_attr_
ap_intf_id
.
attr
,
NULL
,
};
static
const
struct
attribute_group
endo_group
=
{
.
attrs
=
endo_attrs
,
.
name
=
"
SVC
"
,
.
name
=
"
Endo
"
,
};
static
const
struct
attribute_group
*
endo_groups
[]
=
{
&
endo_group
,
&
svc_group
,
NULL
,
};
...
...
@@ -361,19 +407,12 @@ static int create_modules(struct gb_endo *endo)
int
prev_module_id
=
0
;
int
interface_id
;
int
module_id
;
int
interfaces
;
int
max_id
;
/*
* Total number of interfaces:
* - Front: 4
* - Back:
* - Left: max_ribs + 1
* - Right: max_ribs + 1
*/
interfaces
=
4
+
(
endo
->
layout
.
max_ribs
+
1
)
*
2
;
max_id
=
max_endo_interface_id
(
&
endo
->
layout
);
/* Find module corresponding to each interface */
for
(
interface_id
=
1
;
interface_id
<=
interfaces
;
interface_id
++
)
{
for
(
interface_id
=
1
;
interface_id
<=
max_id
;
interface_id
++
)
{
module_id
=
endo_get_module_id
(
endo
,
interface_id
);
if
(
WARN_ON
(
!
module_id
))
...
...
@@ -409,8 +448,8 @@ static int gb_endo_register(struct greybus_host_device *hd,
// FIXME
// Get the version and serial number from the SVC, right now we are
// using "fake" numbers.
strcpy
(
&
endo
->
svc
.
serial_number
[
0
],
"042"
);
strcpy
(
&
endo
->
svc
.
version
[
0
],
"0.0"
);
strcpy
(
&
endo
->
svc
_info
.
serial_number
[
0
],
"042"
);
strcpy
(
&
endo
->
svc
_info
.
version
[
0
],
"0.0"
);
dev_set_name
(
&
endo
->
dev
,
"endo-0x%04x"
,
endo
->
id
);
retval
=
device_add
(
&
endo
->
dev
);
...
...
@@ -423,24 +462,31 @@ static int gb_endo_register(struct greybus_host_device *hd,
return
retval
;
}
struct
gb_endo
*
gb_endo_create
(
struct
greybus_host_device
*
hd
)
struct
gb_endo
*
gb_endo_create
(
struct
greybus_host_device
*
hd
,
u16
endo_id
,
u8
ap_intf_id
)
{
struct
gb_endo
*
endo
;
int
retval
;
u16
endo_id
=
0x4755
;
// FIXME - get endo "ID" from the SVC
endo
=
kzalloc
(
sizeof
(
*
endo
),
GFP_KERNEL
);
if
(
!
endo
)
return
NULL
;
return
ERR_PTR
(
-
ENOMEM
)
;
/* First check if the value supplied is a valid endo id */
if
(
gb_endo_validate_id
(
hd
,
&
endo
->
layout
,
endo_id
))
if
(
gb_endo_validate_id
(
hd
,
&
endo
->
layout
,
endo_id
))
{
retval
=
-
EINVAL
;
goto
free_endo
;
}
if
(
ap_intf_id
>
max_endo_interface_id
(
&
endo
->
layout
))
{
retval
=
-
EINVAL
;
goto
free_endo
;
}
endo
->
id
=
endo_id
;
endo
->
ap_intf_id
=
ap_intf_id
;
/* Register Endo device */
if
(
gb_endo_register
(
hd
,
endo
))
retval
=
gb_endo_register
(
hd
,
endo
);
if
(
retval
)
goto
free_endo
;
/* Create modules/interfaces */
...
...
@@ -454,7 +500,8 @@ struct gb_endo *gb_endo_create(struct greybus_host_device *hd)
free_endo:
kfree
(
endo
);
return
NULL
;
return
ERR_PTR
(
retval
);
}
void
gb_endo_remove
(
struct
gb_endo
*
endo
)
...
...
drivers/staging/greybus/endo.h
View file @
d67a39ab
...
...
@@ -2,6 +2,7 @@
* Greybus endo code
*
* Copyright 2015 Google Inc.
* Copyright 2015 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
...
...
@@ -10,7 +11,7 @@
#define __ENDO_H
/* Greybus "public" definitions" */
struct
gb_svc
{
struct
gb_svc
_info
{
u8
serial_number
[
10
];
u8
version
[
10
];
};
...
...
@@ -36,10 +37,11 @@ struct endo_layout {
};
struct
gb_endo
{
struct
endo_layout
layout
;
struct
device
dev
;
struct
gb_svc
svc
;
struct
endo_layout
layout
;
struct
gb_svc_info
svc_info
;
u16
id
;
u8
ap_intf_id
;
};
#define to_gb_endo(d) container_of(d, struct gb_endo, dev)
...
...
@@ -47,7 +49,8 @@ struct gb_endo {
/* Greybus "private" definitions */
struct
greybus_host_device
;
struct
gb_endo
*
gb_endo_create
(
struct
greybus_host_device
*
hd
);
struct
gb_endo
*
gb_endo_create
(
struct
greybus_host_device
*
hd
,
u16
endo_id
,
u8
ap_intf_id
);
void
gb_endo_remove
(
struct
gb_endo
*
endo
);
u8
endo_get_module_id
(
struct
gb_endo
*
endo
,
u8
interface_id
);
...
...
drivers/staging/greybus/es1.c
View file @
d67a39ab
/*
* Greybus "AP" USB driver
* Greybus "AP" USB driver
for "ES1" controller chips
*
* Copyright 2014 Google Inc.
* Copyright 2014 Linaro Ltd.
* Copyright 2014
-2015
Google Inc.
* Copyright 2014
-2015
Linaro Ltd.
*
* Released under the GPLv2 only.
*/
...
...
@@ -551,14 +551,16 @@ static int ap_probe(struct usb_interface *interface,
bool
bulk_out_found
=
false
;
int
retval
=
-
ENOMEM
;
int
i
;
u16
endo_id
=
0x4755
;
// FIXME - get endo "ID" from the SVC
u8
ap_intf_id
=
0x01
;
// FIXME - get endo "ID" from the SVC
u8
svc_interval
=
0
;
udev
=
usb_get_dev
(
interface_to_usbdev
(
interface
));
hd
=
greybus_create_hd
(
&
es1_driver
,
&
udev
->
dev
,
ES1_GBUF_MSG_SIZE_MAX
);
if
(
!
hd
)
{
if
(
IS_ERR
(
hd
)
)
{
usb_put_dev
(
udev
);
return
-
ENOMEM
;
return
PTR_ERR
(
hd
)
;
}
es1
=
hd_to_es1
(
hd
);
...
...
@@ -659,6 +661,17 @@ static int ap_probe(struct usb_interface *interface,
gb_debugfs_get
(),
es1
,
&
apb1_log_enable_fops
);
/*
* XXX Soon this will be initiated later, with a combination
* XXX of a Control protocol probe operation and a
* XXX subsequent Control protocol connected operation for
* XXX the SVC connection. At that point we know we're
* XXX properly connected to an Endo.
*/
retval
=
greybus_endo_setup
(
hd
,
endo_id
,
ap_intf_id
);
if
(
retval
)
goto
error
;
return
0
;
error:
ap_disconnect
(
interface
);
...
...
drivers/staging/greybus/es2.c
View file @
d67a39ab
...
...
@@ -551,14 +551,16 @@ static int ap_probe(struct usb_interface *interface,
bool
bulk_out_found
=
false
;
int
retval
=
-
ENOMEM
;
int
i
;
u16
endo_id
=
0x4755
;
// FIXME - get endo "ID" from the SVC
u8
ap_intf_id
=
0x01
;
// FIXME - get endo "ID" from the SVC
u8
svc_interval
=
0
;
udev
=
usb_get_dev
(
interface_to_usbdev
(
interface
));
hd
=
greybus_create_hd
(
&
es1_driver
,
&
udev
->
dev
,
ES1_GBUF_MSG_SIZE_MAX
);
if
(
!
hd
)
{
if
(
IS_ERR
(
hd
)
)
{
usb_put_dev
(
udev
);
return
-
ENOMEM
;
return
PTR_ERR
(
hd
)
;
}
es1
=
hd_to_es1
(
hd
);
...
...
@@ -659,6 +661,17 @@ static int ap_probe(struct usb_interface *interface,
gb_debugfs_get
(),
es1
,
&
apb1_log_enable_fops
);
/*
* XXX Soon this will be initiated later, with a combination
* XXX of a Control protocol probe operation and a
* XXX subsequent Control protocol connected operation for
* XXX the SVC connection. At that point we know we're
* XXX properly connected to an Endo.
*/
retval
=
greybus_endo_setup
(
hd
,
endo_id
,
ap_intf_id
);
if
(
retval
)
goto
error
;
return
0
;
error:
ap_disconnect
(
interface
);
...
...
drivers/staging/greybus/gpio.c
View file @
d67a39ab
...
...
@@ -14,7 +14,6 @@
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include "greybus.h"
#include "gpbridge.h"
struct
gb_gpio_line
{
/* The following has to be an array of line_max entries */
...
...
drivers/staging/greybus/greybus.h
View file @
d67a39ab
/*
* Greybus driver and device API
*
* Copyright 2014 Google Inc.
* Copyright 2014 Linaro Ltd.
* Copyright 2014
-2015
Google Inc.
* Copyright 2014
-2015
Linaro Ltd.
*
* Released under the GPLv2 only.
*/
...
...
@@ -23,8 +23,10 @@
#include "kernel_ver.h"
#include "greybus_id.h"
#include "greybus_manifest.h"
#include "greybus_protocols.h"
#include "manifest.h"
#include "endo.h"
#include "svc.h"
#include "module.h"
#include "interface.h"
#include "bundle.h"
...
...
@@ -107,6 +109,8 @@ struct greybus_host_device {
struct
greybus_host_device
*
greybus_create_hd
(
struct
greybus_host_driver
*
hd
,
struct
device
*
parent
,
size_t
buffer_size_max
);
int
greybus_endo_setup
(
struct
greybus_host_device
*
hd
,
u16
endo_id
,
u8
ap_intf_id
);
void
greybus_remove_hd
(
struct
greybus_host_device
*
hd
);
struct
greybus_driver
{
...
...
drivers/staging/greybus/greybus_manifest.h
View file @
d67a39ab
...
...
@@ -4,8 +4,8 @@
* See "Greybus Application Protocol" document (version 0.1) for
* details on these values and structures.
*
* Copyright 2014 Google Inc.
* Copyright 2014 Linaro Ltd.
* Copyright 2014
-2015
Google Inc.
* Copyright 2014
-2015
Linaro Ltd.
*
* Released under the GPLv2 and BSD licenses.
*/
...
...
@@ -42,6 +42,7 @@ enum greybus_protocol {
GREYBUS_PROTOCOL_LOOPBACK
=
0x11
,
GREYBUS_PROTOCOL_I2S_RECEIVER
=
0x12
,
GREYBUS_PROTOCOL_I2S_TRANSMITTER
=
0x13
,
GREYBUS_PROTOCOL_SVC
=
0x14
,
/* ... */
GREYBUS_PROTOCOL_RAW
=
0xfe
,
GREYBUS_PROTOCOL_VENDOR
=
0xff
,
...
...
drivers/staging/greybus/g
pbridge
.h
→
drivers/staging/greybus/g
reybus_protocols
.h
View file @
d67a39ab
...
...
@@ -489,4 +489,61 @@ struct gb_spi_transfer_response {
__u8
data
[
0
];
/* inbound data */
};
/* Version of the Greybus SVC protocol we support */
#define GB_SVC_VERSION_MAJOR 0x00
#define GB_SVC_VERSION_MINOR 0x01
/* Greybus SVC request types */
#define GB_SVC_TYPE_INVALID 0x00
#define GB_SVC_TYPE_PROTOCOL_VERSION 0x01
#define GB_SVC_TYPE_INTF_DEVICE_ID 0x02
#define GB_SVC_TYPE_INTF_HOTPLUG 0x03
#define GB_SVC_TYPE_INTF_HOT_UNPLUG 0x04
#define GB_SVC_TYPE_INTF_RESET 0x05
#define GB_SVC_TYPE_CONN_CREATE 0x06
#define GB_SVC_TYPE_CONN_DESTROY 0x07
struct
gb_svc_intf_device_id_request
{
__u8
intf_id
;
__u8
device_id
;
};
/* device id response has no payload */
struct
gb_svc_intf_hotplug_request
{
__u8
intf_id
;
struct
{
__le32
unipro_mfg_id
;
__le32
unipro_prod_id
;
__le32
ara_vend_id
;
__le32
ara_prod_id
;
}
data
;
};
/* hotplug response has no payload */
struct
gb_svc_intf_hot_unplug_request
{
__u8
intf_id
;
};
/* hot unplug response has no payload */
struct
gb_svc_intf_reset_request
{
__u8
intf_id
;
};
/* interface reset response has no payload */
struct
gb_svc_conn_create_request
{
__u8
intf1_id
;
__u16
cport1_id
;
__u8
intf2_id
;
__u16
cport2_id
;
};
/* connection create response has no payload */
struct
gb_svc_conn_destroy_request
{
__u8
intf1_id
;
__u16
cport1_id
;
__u8
intf2_id
;
__u16
cport2_id
;
};
/* connection destroy response has no payload */
#endif
/* __GB_GPBRIDGE_H__ */
drivers/staging/greybus/i2c.c
View file @
d67a39ab
...
...
@@ -13,8 +13,6 @@
#include <linux/i2c.h>
#include "greybus.h"
#include "gpbridge.h"
struct
gb_i2c_device
{
struct
gb_connection
*
connection
;
...
...
drivers/staging/greybus/protocol.h
View file @
d67a39ab
...
...
@@ -108,7 +108,7 @@ int __init gb_##__protocol##_init(void) \
{ \
return gb_protocol_register(&__protocol); \
} \
void
__exit gb_##__protocol##_exit(void)
\
void
gb_##__protocol##_exit(void)
\
{ \
gb_protocol_deregister(&__protocol); \
} \
...
...
drivers/staging/greybus/pwm.c
View file @
d67a39ab
...
...
@@ -11,8 +11,8 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pwm.h>
#include "greybus.h"
#include "gpbridge.h"
struct
gb_pwm_chip
{
struct
gb_connection
*
connection
;
...
...
drivers/staging/greybus/spi.c
View file @
d67a39ab
...
...
@@ -14,7 +14,6 @@
#include <linux/spi/spi.h>
#include "greybus.h"
#include "gpbridge.h"
struct
gb_spi
{
struct
gb_connection
*
connection
;
...
...
drivers/staging/greybus/svc.c
0 → 100644
View file @
d67a39ab
/*
* SVC Greybus driver.
*
* Copyright 2015 Google Inc.
* Copyright 2015 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include "greybus.h"
#include "greybus_protocols.h"
struct
gb_svc
{
struct
gb_connection
*
connection
;
u8
version_major
;
u8
version_minor
;
};
/* Define get_version() routine */
define_get_version
(
gb_svc
,
SVC
);
static
int
intf_device_id_operation
(
struct
gb_svc
*
svc
,
u8
intf_id
,
u8
device_id
)
{
struct
gb_svc_intf_device_id_request
request
;
request
.
intf_id
=
intf_id
;
request
.
device_id
=
device_id
;
return
gb_operation_sync
(
svc
->
connection
,
GB_SVC_TYPE_INTF_DEVICE_ID
,
&
request
,
sizeof
(
request
),
NULL
,
0
);
}
static
int
intf_reset_operation
(
struct
gb_svc
*
svc
,
u8
intf_id
)
{
struct
gb_svc_intf_reset_request
request
;
request
.
intf_id
=
intf_id
;
return
gb_operation_sync
(
svc
->
connection
,
GB_SVC_TYPE_INTF_RESET
,
&
request
,
sizeof
(
request
),
NULL
,
0
);
}
static
int
connection_create_operation
(
struct
gb_svc
*
svc
,
u8
intf1_id
,
u16
cport1_id
,
u8
intf2_id
,
u16
cport2_id
)
{
struct
gb_svc_conn_create_request
request
;
request
.
intf1_id
=
intf1_id
;
request
.
cport1_id
=
cport1_id
;
request
.
intf2_id
=
intf2_id
;
request
.
cport2_id
=
cport2_id
;
return
gb_operation_sync
(
svc
->
connection
,
GB_SVC_TYPE_CONN_CREATE
,
&
request
,
sizeof
(
request
),
NULL
,
0
);
}
static
int
connection_destroy_operation
(
struct
gb_svc
*
svc
,
u8
intf1_id
,
u16
cport1_id
,
u8
intf2_id
,
u16
cport2_id
)
{
struct
gb_svc_conn_destroy_request
request
;
request
.
intf1_id
=
intf1_id
;
request
.
cport1_id
=
cport1_id
;
request
.
intf2_id
=
intf2_id
;
request
.
cport2_id
=
cport2_id
;
return
gb_operation_sync
(
svc
->
connection
,
GB_SVC_TYPE_CONN_DESTROY
,
&
request
,
sizeof
(
request
),
NULL
,
0
);
}
int
gb_svc_intf_device_id
(
struct
gb_svc
*
svc
,
u8
intf_id
,
u8
device_id
)
{
return
intf_device_id_operation
(
svc
,
intf_id
,
device_id
);
}
EXPORT_SYMBOL_GPL
(
gb_svc_intf_device_id
);
int
gb_svc_intf_reset
(
struct
gb_svc
*
svc
,
u8
intf_id
)
{
return
intf_reset_operation
(
svc
,
intf_id
);
}
EXPORT_SYMBOL_GPL
(
gb_svc_intf_reset
);
int
gb_svc_connection_create
(
struct
gb_svc
*
svc
,
u8
intf1_id
,
u16
cport1_id
,
u8
intf2_id
,
u16
cport2_id
)
{
return
connection_create_operation
(
svc
,
intf1_id
,
cport1_id
,
intf2_id
,
cport2_id
);
}
EXPORT_SYMBOL_GPL
(
gb_svc_connection_create
);
int
gb_svc_connection_destroy
(
struct
gb_svc
*
svc
,
u8
intf1_id
,
u16
cport1_id
,
u8
intf2_id
,
u16
cport2_id
)
{
return
connection_destroy_operation
(
svc
,
intf1_id
,
cport1_id
,
intf2_id
,
cport2_id
);
}
EXPORT_SYMBOL_GPL
(
gb_svc_connection_destroy
);
static
int
gb_svc_intf_hotplug_recv
(
struct
gb_operation
*
op
)
{
struct
gb_message
*
request
=
op
->
request
;
struct
gb_svc_intf_hotplug_request
*
hotplug
;
u8
intf_id
;
u32
unipro_mfg_id
;
u32
unipro_prod_id
;
u32
ara_vend_id
;
u32
ara_prod_id
;
if
(
request
->
payload_size
<
sizeof
(
*
hotplug
))
{
dev_err
(
&
op
->
connection
->
dev
,
"short hotplug request received
\n
"
);
return
-
EINVAL
;
}
hotplug
=
request
->
payload
;
/*
* Grab the information we need.
*
* XXX I'd really like to acknowledge receipt, and then
* XXX continue processing the request. There's no need
* XXX for the SVC to wait. In fact, it might be best to
* XXX have the SVC get acknowledgement before we proceed.
* */
intf_id
=
hotplug
->
intf_id
;
unipro_mfg_id
=
hotplug
->
data
.
unipro_mfg_id
;
unipro_prod_id
=
hotplug
->
data
.
unipro_prod_id
;
ara_vend_id
=
hotplug
->
data
.
ara_vend_id
;
ara_prod_id
=
hotplug
->
data
.
ara_prod_id
;
/* FIXME Set up the interface here; may required firmware download */
return
0
;
}
static
int
gb_svc_intf_hot_unplug_recv
(
struct
gb_operation
*
op
)
{
struct
gb_message
*
request
=
op
->
request
;
struct
gb_svc_intf_hot_unplug_request
*
hot_unplug
;
u8
intf_id
;
if
(
request
->
payload_size
<
sizeof
(
*
hot_unplug
))
{
dev_err
(
&
op
->
connection
->
dev
,
"short hot unplug request received
\n
"
);
return
-
EINVAL
;
}
hot_unplug
=
request
->
payload
;
intf_id
=
hot_unplug
->
intf_id
;
/* FIXME Tear down the interface here */
return
0
;
}
static
int
gb_svc_intf_reset_recv
(
struct
gb_operation
*
op
)
{
struct
gb_message
*
request
=
op
->
request
;
struct
gb_svc_intf_reset_request
*
reset
;
u8
intf_id
;
if
(
request
->
payload_size
<
sizeof
(
*
reset
))
{
dev_err
(
&
op
->
connection
->
dev
,
"short reset request received
\n
"
);
return
-
EINVAL
;
}
reset
=
request
->
payload
;
intf_id
=
reset
->
intf_id
;
/* FIXME Reset the interface here */
return
0
;
}
static
int
gb_svc_request_recv
(
u8
type
,
struct
gb_operation
*
op
)
{
switch
(
type
)
{
case
GB_SVC_TYPE_INTF_HOTPLUG
:
return
gb_svc_intf_hotplug_recv
(
op
);
case
GB_SVC_TYPE_INTF_HOT_UNPLUG
:
return
gb_svc_intf_hot_unplug_recv
(
op
);
case
GB_SVC_TYPE_INTF_RESET
:
return
gb_svc_intf_reset_recv
(
op
);
default:
dev_err
(
&
op
->
connection
->
dev
,
"unsupported request: %hhu
\n
"
,
type
);
return
-
EINVAL
;
}
}
/*
* Do initial setup of the SVC.
*/
static
int
gb_svc_device_setup
(
struct
gb_svc
*
gb_svc
)
{
/* First thing we need to do is check the version */
return
get_version
(
gb_svc
);
}
static
int
gb_svc_connection_init
(
struct
gb_connection
*
connection
)
{
struct
gb_svc
*
svc
;
int
ret
;
svc
=
kzalloc
(
sizeof
(
*
svc
),
GFP_KERNEL
);
if
(
!
svc
)
return
-
ENOMEM
;
svc
->
connection
=
connection
;
connection
->
private
=
svc
;
ret
=
gb_svc_device_setup
(
svc
);
if
(
ret
)
kfree
(
svc
);
return
ret
;
}
static
void
gb_svc_connection_exit
(
struct
gb_connection
*
connection
)
{
struct
gb_svc
*
svc
=
connection
->
private
;
if
(
!
svc
)
return
;
kfree
(
svc
);
}
static
struct
gb_protocol
svc_protocol
=
{
.
name
=
"svc"
,
.
id
=
GREYBUS_PROTOCOL_SVC
,
.
major
=
0
,
.
minor
=
1
,
.
connection_init
=
gb_svc_connection_init
,
.
connection_exit
=
gb_svc_connection_exit
,
.
request_recv
=
gb_svc_request_recv
,
};
int
gb_svc_protocol_init
(
void
)
{
return
gb_protocol_register
(
&
svc_protocol
);
}
void
gb_svc_protocol_exit
(
void
)
{
gb_protocol_deregister
(
&
svc_protocol
);
}
drivers/staging/greybus/svc.h
0 → 100644
View file @
d67a39ab
/*
* Greybus SVC code
*
* Copyright 2015 Google Inc.
* Copyright 2015 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
#ifndef __SVC_H
#define __SVC_H
struct
gb_svc
;
int
gb_svc_intf_device_id
(
struct
gb_svc
*
svc
,
u8
intf_id
,
u8
device_id
);
int
gb_svc_intf_reset
(
struct
gb_svc
*
svc
,
u8
intf_id
);
int
gb_svc_connection_create
(
struct
gb_svc
*
svc
,
u8
intf1_id
,
u16
cport1_id
,
u8
intf2_id
,
u16
cport2_id
);
int
gb_svc_connection_destroy
(
struct
gb_svc
*
svc
,
u8
intf1_id
,
u16
cport1_id
,
u8
intf2_id
,
u16
cport2_id
);
#endif
/* __SVC_H */
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