Institutionen för systemteknik Department of Electrical Engineering Rugged Portable Communication System Examensarbete

Institutionen för systemteknik Department of Electrical Engineering Rugged Portable Communication System Examensarbete
Institutionen för systemteknik
Department of Electrical Engineering
Examensarbete
Rugged Portable Communication System
Examensarbete utfört i Computer Engineering
vid Tekniska högskolan vid Linköpings universitet
av
Juha Kamula och Rikard Hansson
LiTH-ISY-EX--13/4729--SE
Linköping 2013
Department of Electrical Engineering
Linköpings universitet
SE-581 83 Linköping, Sweden
Linköpings tekniska högskola
Linköpings universitet
581 83 Linköping
Rugged Portable Communication System
Examensarbete utfört i Computer Engineering
vid Tekniska högskolan i Linköping
av
Juha Kamula och Rikard Hansson
LiTH-ISY-EX--13/4729--SE
Handledare:
Olle Seger
isy, Linköpings universitet
Mikael Ljung
Saab AB
Examinator:
Olle Seger
isy, Linköpings universitet
Linköping, 29 November, 2013
Avdelning, Institution
Division, Department
Datum
Date
Division of Computer Engingeering
Department of Electrical Engineering
Linköpings universitet
SE-581 83 Linköping, Sweden
Språk
Language
Rapporttyp
Report category
ISBN
Svenska/Swedish
Licentiatavhandling
ISRN
Engelska/English
Examensarbete
C-uppsats
D-uppsats
Övrig rapport
2013-11-29
—
LiTH-ISY-EX--13/4729--SE
Serietitel och serienummer ISSN
Title of series, numbering
—
URL för elektronisk version
http://www.da.isy.liu.se
http://www.ep.liu.se
Titel
Title
Rugged Portable Communication System
Författare Juha Kamula och Rikard Hansson
Author
Sammanfattning
Abstract
Todays modern warfare puts high demands on military equipment. Where
soldiers are concerned, types of communication equipment such as radios, displays
and headsets play a central role. A modern soldier is often required to maintain
communication links with other military units. These units can, for example,
consist of platoon commanders, headquarters and other soldiers. If the soldier
needs to make a report to several units, the message needs to be sent to several
radio networks that are connected to these separate units. This multiplicity in
turn requires several items of radio equipment connected to the radio network
frequencies. Considering all the communication equipment that is used by a
modern soldier, the parallel data flow and all the weight a soldier needs to carry,
can get quite extensive.
At Saab AB it has been proven that a combination of powerful embedded hardware
platforms and cross platform software fulfills the communication needs. However,
the weight issue still remains as these embedded platforms are quite bulky and
hard to carry. In order to increase the portability, a tailored Android application
for smaller low-power embedded hardware platform has been developed at Saab
AB. Saab AB has also developed a portable analogue interconnection unit for
connecting three radios and a headset, the SKE (Sammankopplingsenhet)a .
Saab AB intends to develop a new product for soldiers, the RPCS (Rugged
Portable Communication System), with capacities of running the Android application and combining the audio processing functionality of the SKE. This thesis
focuses on developing a hardware platform prototype for the RPCS using Beagleboard. The SKE audio processing functionality is developed as a software application running on the Beagleboard.
Nyckelord
Keywords
Beagleboard, GStreamer, ALSA System-on-Chip, TI TLV320AIC31
a Swedish
for Interconnection Unit.
Acknowledgments
First of all, we would like to thank Saab AB for the opportunity of making this
thesis work. It has been an incredible experience where a lot has been learnt.
Special thanks to Mikael Ljung and Erik Gustavsson at Saab AB for all the trust
and supervision.
Thanks to the department of electrical engineering at Linköping University for all
the support during this thesis work, especially Tomas Svensson and Olle Seger for
making this possible.
Last of all, thanks to all of our friends and family for all the support and patience
through all these years. You know who you are!
v
Abstract
Todays modern warfare puts high demands on military equipment. Where soldiers are concerned, types of communication equipment such as radios, displays
and headsets play a central role. A modern soldier is often required to maintain
communication links with other military units. These units can, for example, consist of platoon commanders, headquarters and other soldiers. If the soldier needs
to make a report to several units, the message needs to be sent to several radio
networks that are connected to these separate units. This multiplicity in turn requires several items of radio equipment connected to the radio network frequencies.
Considering all the communication equipment that is used by a modern soldier,
the parallel data flow and all the weight a soldier needs to carry, can get quite
extensive.
At Saab AB it has been proven that a combination of powerful embedded hardware
platforms and cross platform software fulfills the communication needs. However,
the weight issue still remains as these embedded platforms are quite bulky and
hard to carry. In order to increase the portability, a tailored Android application
for smaller low-power embedded hardware platform has been developed at Saab
AB. Saab AB has also developed a portable analogue interconnection unit for connecting three radios and a headset, the SKE (Sammankopplingsenhet)1 .
Saab AB intends to develop a new product for soldiers, the RPCS (Rugged Portable
Communication System), with capacities of running the Android application and
combining the audio processing functionality of the SKE. This thesis focuses on
developing a hardware platform prototype for the RPCS using Beagleboard. The
SKE audio processing functionality is developed as a software application running
on the Beagleboard.
1 Swedish
for Interconnection Unit.
vii
Abbreviations
ALSA
Advanced Linux Sound Architecture
ASoC
ALSA System-on-Chip
CPU
Central Processing Unit
DAI
Digital Audio Interface
I2C
Inter-Integrated Circuit
I2S
Inter-IC sound
McBSP
Multi-channel Buffered Serial Port
OS
Operating System
PCB
Printed Circuit Board
RDRM
Rugged ”Dödräkningsmodul”
RPCB
Rugged Portable Communication Battery
RPCD
Rugged Portable Communication Display
RPCS
Rugged Portable Communication System
RPCU
Rugged Portable Communication Unit
RS232
Recommended Standard 232
SKE
Sammankopplingsenhet (Swedish word for Interconnection
Unit)
SoC
System-on-Chip
SVM
System Validation Matrix
ix
Contents
1 Introduction
1.1 Background . . . . .
1.2 Problem Formulation
1.3 Objectives and Aim
1.4 Thesis Structure . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
2
3
3
2 Requirements Elicitation
2.1 The SKE . . . . . . . . . . . . . . . . . . . . . . . .
2.1.1 The External Interfaces . . . . . . . . . . . .
2.1.2 The Internal Functionality . . . . . . . . . . .
2.2 Adapting SKE requirements . . . . . . . . . . . . . .
2.3 Analyzing the RPCU Subsystem . . . . . . . . . . .
2.3.1 Functionality for the Interfacing Subsystems
2.3.2 Android Platform . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
5
7
8
10
10
11
3 RPCU System Design
3.1 Design Methodology . . . . . .
3.1.1 The Hardware Layer . .
3.1.2 The OS Layer . . . . . .
3.1.3 The Applications Layer
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
13
15
16
4 Implementation of the RPCU
4.1 The Hardware Layer . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.1 Physical Interconnections . . . . . . . . . . . . . . . . . .
4.2 The OS Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.1 Configuring the Expansion Header . . . . . . . . . . . . .
4.2.2 ALSA System on Chip . . . . . . . . . . . . . . . . . . . .
4.2.2.1 Default ASoC Configuration for the Beagleboard
4.2.2.2 Modifying the ASoC for the Beagleboard . . . .
4.2.3 Building and Booting the modified Android sources . . .
4.3 The Application Layer . . . . . . . . . . . . . . . . . . . . . . . .
4.3.1 GStreamer SKE Application . . . . . . . . . . . . . . . .
4.3.2 Configuration Handling Application . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
17
17
17
20
20
21
22
24
27
29
29
31
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5 Verification
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
35
xi
6 Conclusion
7 Appendices
7.1 GStreamer application code, header file gst_ske.h .
7.2 GStreamer application code, body file gst_ske.c . .
7.3 Configuration handling code, header file config.h .
7.4 Configuration handling code, body file config.c . .
7.5 Help functions code, header file helpers.h . . . . .
7.6 Help functions code, header file helpers.c . . . . . .
7.7 Modified code for omap3beagle.c . . . . . . . . . .
7.8 Modified code for board-omap3beagle.c . . . . . .
Bibliography
37
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
39
39
40
45
46
50
51
51
56
79
Contents
xiii
List of Figures
1.1
Overview of the RPCS . . . . . . . . . . . . . . . . . . . . . . . . .
2
2.1
2.2
The SKE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A basic block scheme of the SKE internal audio processing chain .
6
7
3.1
3.2
Overview of the design methodology . . . . . . . . . . . . . . . . .
Overview of the Beagleboard integrated with the SKE . . . . . . .
13
14
The physical routing part of the overall design methodology . . . .
Integration of SKE into expansion header of Beagleboard . . . . .
The ASoC part of the overall design methodology . . . . . . . . . .
Kernel print for ASoC part when booting Android with the modified
Kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.5 The GStreamer SKE Application part of the overall design methodology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.6 Overview of the pipeline configuration. The above picture displays
the pipeline in stereo mode whereas the below one displays the
pipeline in mono mode. . . . . . . . . . . . . . . . . . . . . . . . .
4.7 The architecture of the basic configuration tool . . . . . . . . . . .
4.8 State machine description of Configuration handling together with
GStreamer application . . . . . . . . . . . . . . . . . . . . . . . . .
4.9 The configuration menu . . . . . . . . . . . . . . . . . . . . . . . .
4.10 Configuration of headset . . . . . . . . . . . . . . . . . . . . . . . .
17
19
20
4.1
4.2
4.3
4.4
28
29
30
31
32
32
33
List of Tables
3.1
Pin-mux routing between Beagleboard and SKE . . . . . . . . . .
15
4.1
Integration signals from SKE . . . . . . . . . . . . . . . . . . . . .
18
Chapter 1
Introduction
1.1
Background
Due to the rapid general development of technology, the development of warfare
equipment needs to follow the same quick advancement, in order to not become
outdated. Over time, the need of lighter equipment with more functionality has
increased. Where soldiers are concerned, types of communication equipment, such
as radios, displays and headsets play a central role. The soldier is often required
to maintain communication links with several different units. These units can,
for example, consist of platoon commanders, headquarters and other soldiers. If
the soldier needs to make a report to several units, the message needs to be sent
to several radio networks that are connected to these separate units. This multiplicity in turn requires several items of radio equipment connected to the radio
network frequencies. Considering all the communication equipment that is used
by a modern soldier, the parallel data flow can get quite extensive.
Equipment used in the military must be able to withstand rough environmental
conditions. For this purpose there are special military standards1 used for testing
the equipment. In most cases, in order to pass the tests, the equipment is required
to be rugged2 . This implies that the equipment is usually heavy. Adding all the
communication equipment to the equation, one can imagine all the weight that a
soldier needs to carry.
In order to centralize the data flow and to maintaining low weight, Saab AB has
developed an analogue interconnection unit called the SKE (Sammankopplingsenhet). The SKE has the capability to connect three radio-equipment units and one
headset into it. It provides basic audio processing and routing functionality for
communication to and from the connected equipment.
1 see http://en.wikipedia.org/wiki/MIL-STD-810 for MIL-STD-810 which specifies the environmental engineering considerations and laboratory tests.
2 In order to withstand harsh environmental conditions and reckless handling, the housing of
the equipment is reinforced. In military terms equipment of this type is called rugged equipment.
1
2
Introduction
In order to increase the adaptability and flexibility it is common to encapsulate
more functionality in software modules. These software modules are used in applications running on different embedded platforms. Despite that the SKE fulfills
its purpose of handling communication equipment, it lacks the functionality of
these embedded platforms. In order to address these issues, Saab AB has the
intention of developing an embedded platform which would contain the SKE functionality instead. In addition, Saab AB also has an intention of running Android
applications on the platform.
1.2
Problem Formulation
The platform that Saab AB has the intention of developing is called RPCU. The
RPCU shall be the main computing platform of a future product called RPCS.
The goal with the RPCS is to replace the SKE and to have the ability to run
Android applications. The RPCS is displayed in figure 1.1 and consists of four
sub-systems:
• Rugged Portable Communication Unit (RPCU) - The core of the system,
handles all data processing.
• Rugged Portable Communication Display (RPCD) - The graphical user interface of the system.
• Rugged Portable Battery Unit (RPBU) - The Power supply of the system.
• Rugged "dödräkningsmodul" (RDRM) - Provides GPS and locationing data.
Figure 1.1. Overview of the RPCS
The customer at Saab AB requests a prototype to be developed of the RPCU
subsystem. In order to ensure possible usage of android applications in the future,
1.3 Objectives and Aim
3
the prototype shall be able to run an Android operating system. The SKE audio
processing functionality shall be maintained through an application running on the
prototype. The prototype must also be developed within an architecture family
that supports future upgrades.
1.3
Objectives and Aim
The objective of this thesis is focused on developing and validating a prototype
of the RPCU subsystem running the SKE audio processing functionality. The
objective is divided into the following goals:
1. SKE analysis and pre-study - Analyzing the requirements and functionality
of the SKE and adapting them to the RPCS.
2. System design - Specifying the system design using Beagleboard as the embedded platform.
3. Implement additional external audio interface - The SKE is reused and integrated into the Beagleboard to provide additional external audio interfaces.
The SKE audio processing functionality is implemented as an application
running on the Beagleboard.
4. Validation and verification - Validating and verifying the hardware, software
and integration of the RPCU.
1.4
Thesis Structure
Introduction
The introduction chapter starts by describing the background of this thesis. Derived from the background, the problem formulation and aim of this thesis are
described.
Requirements Elicitation
In order to set the baseline of this thesis and to be able to verify the end-product,
RPCS, a requirements elicitation is done. The requirements are elicited from SKE
documentation and new requirements stated for the RPCS. The requirements baseline of this thesis is formed by applying a method for separating the requirements
into a group of prototype requirements for the RPCU. All the requirements are
documented in a requirements specification for the RPCS.
RPCU System Design
Based on the requirements baseline for the RPCU, a system design is made. The
Beagleboard is chosen as the embedded platform for the RPCU. A layered system
design approach, which is classic for embedded systems, is used to define the different components of each layer. With this approach a more clear picture can be
drawn of what needs to be accomplished in each layer. All the components are
4
Introduction
used to get a complete system.
Implementation of the RPCU
In this chapter the system design principles are applied when implementing the
layered components of the RPCU. The layered components consists all from physical hardware integration, modification of the Linux Kernel to coding of software
applications.
Verification
To wrap the design and implementation phase up, a functional verification3 of the
RPCU is done. The verification is focused on the implemented components of each
layer. A complete statement is also given on the whole integration.
Conclusion
The Conclusion chapter sums up the thesis by discussing pros and cons with the
chosen system design and implementation. By reading this chapter a subsequent
developer should be able to get the overall picture of the project status and how
to proceed with the development.
3 As this thesis focuses on developing a prototype of the RPCU, the verification is focused on
function instead of fulfilling requirements.
Chapter 2
Requirements Elicitation
The SKE is an analogue interconnection unit, capable of processing and routing
several audio input/output sources. A known issue with analogue hardware designs is their poor flexibility when it comes to performance upgrades or adding
additional functionality once the design has been finalized. In order to overcome
these issues, a preferable solution is to use a layered system design when designing
the RPCU. In this case the audio processing functionality is implemented as an
application running on an embedded hardware platform, the Beagleboard.
Saab AB has stated that the requirements elicitation shall be based on
the RPCS, not only the RPCU. A complete set of requirements is
needed in order to ensure that the sub-systems are integrable.
In order to be able to verify the RPCU prototype, the requirements that apply for
the RPCU needs to be elicited. The requirements elicitation consists of:
• Analyzing the SKE functionality, pertaining requirements and adapting them
for the RPCU (by request of the customer at Saab AB, the same functionality
shall be maintained by the RPCU).
• Elicitation of new requirements that shall be maintained by the RPCU, for
example requirements put on the external interfaces of the RPCU in order
to support communication to the other subsystems.
2.1
2.1.1
The SKE
The External Interfaces
The SKE uses three audio input interfaces for connecting communication devices
located at the bottom side of the device:
• RA1: input interface for connecting Radio device 1
5
6
Requirements Elicitation
• RA2: input interface for connecting Radio device 2
• IC: input interface for connecting Intercom device
An overview of the SKE is provided in Figure 2.1 below.
Figure 2.1. The SKE
The intercom interface is intended for communication equipment mounted inside
vehicles. An output interface named HS intended for a headset is located at the
upper left side of the SKE.
In the military it is very common that several different communication equipments
are used, such as different radios and headset with different audio parameters (e.g.
signal levels, gain, frequency bands etc). To be able to handle different communication equipment, the SKE needs to be flexible to allow several different configurations. The configurations correspond to the various differing audio parameters
and demands of the communication equipment. Without this level of flexibility,
distorted signal levels may arise at the output equipment. The input interface seen
at the upper right side is the USB interface intended for loading configurations
and firmware to the SKE.
A display and four buttons are centrally located on the SKE, functioning as a
simple user interface for enabling configurations and controlling audio processing
functionality. The SKE also has buttons located at the two long-edges, one for
volume control and one for activating the communication from the audio input
sources, located at the bottom side.
2.1 The SKE
2.1.2
7
The Internal Functionality
The SKE is a bidirectional audio router with simple processing functionality for
enabling communication to and from multiple audio sources. An overview of the
audio processing chain can be seen in Figure 2.2. The main blocks of the audio
processing chain are two Texas Instruments TLV320AIC31 [7] low power stereo
audio codecs, a microcontroller and some output amplifiers.
Figure 2.2. A basic block scheme of the SKE internal audio processing chain
Bidirectional in this case refers to the ability of the SKE to handle audio input
signals received from the following interfaces:
• Radio 1 (RA1)
• Radio 2 (RA2)
• Intercom (IC)
The audio codecs mix the incoming audio signals and processes the mixed audio
signal, depending on which audio parameters are set on the SKE. The audio signal
is then amplified before it is sent to the headset, or if the audio input source is
8
Requirements Elicitation
HS or IC, the audio signal is also sent to one of the radios. A button on the SKE
selects the active communication channel.
The parameters that set up the audio processing chain is controlled by a microcontroller. The microcontroller is connected to a memory that contains the
configurations that are loaded into the SKE. As can be seen in figure 2.2, the
microcontroller is connected to the audio codecs through a demultiplexer. The
interface for controlling the audio parameters of the audio codecs is I2C, and the
reason for using a demultiplexer is because of the addressing design of the audio
codec. The audio codec is designed to respond to the hardcoded I2C address of
0x18. To be able to address both codecs, the microcontroller selects one of the
demultiplexer channels, addresses the selected audio codec and sets up the audio
parameters of that audio codec.
2.2
Adapting SKE requirements
The method to determine the requirements of the RPCS is a requirements analysis
categorizing the requirements by the following decision factors:
1. Adaptability - Is the requirement adaptable for RPCS?
2. Maturity - Is the requirement existent at prototype or product stage?
3. Priority - Which priority does the requirement have according to the customer?
Essentially all of the functionality is derived and based on the dozens of functional
requirements regarding the electrical systems/subsystems of the SKE.
A document that is produced early in the design process at Saab AB for each
product is the System Verification Matrix (SVM). The SVM is an extension of the
requirement specification where each requirement is analyzed deeper with focus
on verification. The objective in this case will be to analyze the requirements and
verification methods in the SKE SVM [1]. In sequence with the requirement analysis, a decision is taken if the requirement is adaptable or not. The outcome of
each requirement is either to transfer the requirement directly (fully adaptable),
translation of the requirement (partly adaptable) or removing the requirement
(not adaptable).
The following requirements taken from the SKE SVM to provide examples of how
the adaptability factor is used:
”The SKE shall have a volume control to adjust the volume for connected headset”
Basic volume adjustment is a requirement which fits into the fully adaptable requirement category, as any device that handles audio needs to have such functionality.
2.2 Adapting SKE requirements
9
The major part of the partly adaptable requirements relates to analog/digital
transformations. One requirement is that audio shall be delivered to the headset
with an output power of 96 dB. Another requirement, shown below, specifies demands of the audio quality:
”The SKE shall not distort the audio to/from the headset interface”
Related to audio bit depth and the theories of signal-to-noise ratio (SNR) in electrical engineering, a guiding principle is that the SNR is increased by 6 dB for
1-bit increase in bit depth. There are many factors in the audio signal chain that
may affect the audio quality, but a crucial parameter is that correct bit depth is
selected in the design to ensure that the audio is not distorted. The requirements
above can for that reason be seen as partly adaptable and translated into the following principal requirement:
”The digital audio bit depth must be at least 16 bits”
The requirements that end up as not adaptable, are either discarded or totally
modified. The requirements that were modified still held some vital functionality
that could not be discarded (but still was not adaptable) or had to be kept and
modified by request of the customer. The below requirement is taken from the
SVM shows a requirement which was modified by the request of customer.
”The SKE shall be operated with standard (AAA or AA) Alkaline batteries”
Into:
”The RPCS shall be operated with an external battery (RPBU)”
The SVM contains a lot of non-functional requirements such as physical size,
weight and interface connector types that are requirements applied at the product
stage1 . All the requirements need to be included into the requirement specification
for RPCS by request of the customer. The goal is to create a prototype with an
end-product perspective. With this method an abstraction can be made to split
requirements into two subgroups, prototype stage and product stage requirements.
This is the maturity factor.
The priority factor can be seen as a review by the customer of the remaining requirements, with an intention to filter in which order functionality needs to mature
for the prototype. Requirements with maturity = product are not marked with
any priority2
An example is shown below, displaying three requirements taken from the RPCS
Requirement Specification [2].
1 requirements
2 Product
that do not affect the internal functionality
requirements are outside of scope of this thesis.
10
Requirements Elicitation
Requirement
3.1.22
4.3.3
6.1.3
Requirement description
The RPCS shall have a volume
control to adjust the volume for
connected headset
It shall be possible to power the
RPCS via the intercom interface
The RPCS shall be protected
against intrusion from dust and
water
Maturity
Prototype
Priority
1
Prototype
2
Product
In this thesis the focus is on the requirements that fall under the properties maturity = prototype and priority = 1.
2.3
Analyzing the RPCU Subsystem
In the previous section the method of analyzing and adapting the old SKE requirements into a new requirements specification was described. This thesis focuses on
the main sub-system RPCU, which implies in that the focus is aimed at the requirements applied on the RPCU sub-system. It has to be taken into account that
functionality implemented in the RPCU are dependant of the other sub-systems,
such as interfaces, data types etc.
2.3.1
Functionality for the Interfacing Subsystems
The RPCU sub-system shall interface the three sub-systems RPCD, RDRM and
RPCB.
RPCD - Rugged Portable Communication Display
The RPCD is the Graphical User Interface (GUI) of the RPCS.
The SKE GUI and its containing functionality are lifted into the RPCD. A video
and data (for buttons) interface is required between the RPCD and RPCU. A
requirement from the customer is that DVI-D be used for video communication
and that USB is used for data communication.
RDRM - Rugged Dödräkningsmodul3
The RDRM is a subsystem that sends coordinates of the soldiers location based
on a GPS. When no GPS connection can be established the RDRM takes over and
calculates the location based on steps and direction. The RDRM is an unit that
has no connection to the SKE. A requirement from the customer is that RS232 be
used for sending data from the RDRM to the RPCU.
RPBU - Rugged Portable Battery Unit
The RPBU is an external battery unit for supplying power to all the other subsystems. In the SKE power is supplied via standard (AAA or AA) batteries. As
3 Swedish
for Death Counting Module
2.3 Analyzing the RPCU Subsystem
11
functionality expands a more pliable power solution must be applied. By request
of the customer the RPCS is supplied by an external power unit, the RPBU.
2.3.2
Android Platform
By request of the customer the RPCS hardware platform must be able to run na
Android operating system to enable future support for Android applications.
Chapter 3
RPCU System Design
In this chapter the system design is defined in order to satisfy the requirements.
The system design is split into three layers; the hardware layer, the operating
system (OS) layer and the applications layer. See figure 3.1 below for an overview.
Figure 3.1. Overview of the design methodology
3.1
3.1.1
Design Methodology
The Hardware Layer
The design of the hardware layer targets the physical components, in this case
selecting platform hardware. The Beagleboard [4] is selected as the main hardware
platform for the RPCU. The Beagleboard provides good performance, support for
Android and compliance in all of the requirements regarding physical interfaces:
• USB for RPCD
• DVI-D for RPCD
13
14
RPCU System Design
• RS232 for RDRM
• Expansion header1 for additional audio interfaces.
The RPCU shall provide the same audio interfaces as the SKE; RA1, RA2 and
IC. This forces us to use the expansion header. In order to save work effort, the
SKE is modified2 and integrated with the Beagleboard using the expansion header.
The expansion header interface on the beagleboard is configured as McBSP3
(Multi-channel Buffered Serial Port) and used to get a data channel between the
SKE and the Beagleboard. Figure 3.2 shows a complete overview of the audio
processing chain after modification.
For replacing the TLV320AIC31 audio codec configuration functionality, formerly
handled by the microcontroller, two pins on the expansion header are configured
for I2C and one pin as General Purpose In/out (GPIO). The configuration of the
expansion header is controlled by a multiplexer that is set up in the OS Layer.
Figure 3.2. Overview of the Beagleboard integrated with the SKE
1 The expansion header is an interface on the Beagleboard that provides the flexibility of
integrating different external units such as additional audio sources.
2 The TLV320AIC31 audio codec contains digital in- and outputs, but these are grounded and
not used in the SKE. The core of the SKE, the microcontroller, configures the audio codecs and
disables the digital interfaces. The SKE PCB card is modified to enable usage of the digital
interfaces.
3 The MCBSP interfaces are specific for the OMAP processor, see [8] for further information.
3.1 Design Methodology
3.1.2
15
The OS Layer
Android is an operating system that is built on top of a Linux kernel. The Advanced Linux Sound Architecture (ALSA) is an open source software framework
and a part of the Linux core that handles audio. For embedded systems, a layer
for providing ALSA support called ASoC [3] (ALSA System-on-Chip) is used. The
ASoC is developed as a machine driver in the Linux kernel for specifying connections between the audio related components in the embedded system.
The embedded Android sources used in this design are called Rowboat [10]. The
Rowboat Android sources are specifically designed for Texas Instruments (TI) devices, such as the Beagleboard which is built on the TI OMAP3530 applications
processor [8]. The Rowboat Android sources provide different configurations for
different TI devices.
The default configuration for the Beagleboard uses the on-chip TWL4030 audio
codec. In order to make the Beagleboard communicate with the SKE at the OS
Layer, modifications has to be done in the ASoC machine driver. The modifications imply inactivation of the TWL4030 audio codec and activation of the
TLV320AIC31 audio codecs.
The expansion header has also to be configured correctly to allow the TLV320AIC31
audio codecs to communicate with the Beagleboard through the McBSP interface.
Table 3.1 shows the pin connections that will be used to connect the SKE and
Beagleboard.
Expansion
header
number
4
5
6
8
10
12
14
16
18
23
24
OMAP pin
pin
AB26
AF3
AA25
AE5
AB25
V21
W21
K26
U21
AE15
AF15
Expansion
header
configuration
McBSP3_DX
GPIO_138
McBSP3_CLKX
McBSP3_FSX
McBSP3_DR
McBSP1_DX
McBSP1_CLKX
McBSP1_FSX
McBSP1_DR
I2C2_SDA
I2C2_SCL
TLV320AIC31
pin in SKE
Din (Codec #1)
Codec mux
Bclk (Codec #1)
Wclk (Codec #1)
Dout (Codec #1)
Din (Codec #2)
Bclk (Codec #2)
Wclk (Codec #2)
Dout (Codec #2)
Codec mux
Codec mux
Table 3.1. Pin-mux routing between Beagleboard and SKE
The work that must be done in the OS Layer can be split into the following steps:
16
RPCU System Design
1. Configuration of the expansion header.
2. Modification of the ASoC machine driver in the Android Rowboat sources.
3. Building the modified Android Rowboat sources.
4. Verifying the built sources by running them on the Beagleboard.
3.1.3
The Applications Layer
At the Applications layer, the SKE audio processing functionality is implemented
in form of a GStreamer [6] application developed in C. To complete the audio
processing chain, the GStreamer application is set up to communicate with the
ALSA API. To provide a concept of how the SKE configuration handling could
work together with the GStreamer application, a basic configuration handling application is developed.
GStreamer is portable to Android. However this thesis does not cover the parts of
adapting GStreamer to Android, but to prove that GStreamer is a good candidate
for implementing the audio processing functionality.
Chapter 4
Implementation of the
RPCU
4.1
4.1.1
The Hardware Layer
Physical Interconnections
In order to provide a physical connection between the Beagleboard and the SKE,
the pins for McBSP and I2C must be located on the Beagleboard expansion header.
The pins that connect from the SKE can then be routed to the corresponding pins
of the expansion header.
Figure 4.1. The physical routing part of the overall design methodology
According to table 20 in [4], the expansion header is configurable to multiplex
different functionalities. Each pin number between 3 - 24 can be multiplexed in
seven different ways to allow a specific functionality for a specific pin. Pins 23 and
24 are configurable for I2C by multiplexing a zero.
17
18
Implementation of the RPCU
The OMAP processor [8] has five McBSP interfaces in total, McBSP1 - McBSP5.
However, the Beagleboard is designed to only provide support for McBSP1 and
McBSP3 through the expansion header. As there are only two audio codecs on
the SKE, two McBSP channels are sufficient.
By definition of the OMAP technical reference manual [8], McBSP1 uses a 6-pin
configuration whilst McBSP3 uses a 4-pin configuration. The exact pin names and
usage of the McBSP channels can be seen in figure 21-3 and 21-4 in the OMAP
technical reference manual. Signals DX and DR are used for data-transmit and
data-receive, CLKX and FSR are used for transmit clock (bit clock) and transmit
frame synchronization (word clock). For McBSP1 there is no use for the signals
FSR and CLKR, they are thus disregarded.
For the audio codec multiplexer, an arbitrary unused pin can be configured as
general purpose (GPIO), in this case pin 5. Pins 1-2 (VDD) and 27-28 (GND) are
used for powering the SKE. The SKE uses voltage levels of 1.8V and 3.3V. Pin 1
in the expansion header can be used to supply 1.8V. In order to solve the 3.3V
supply, Pin 2 in the expansion header that provides a 5V power supply, is level
shifted to 3.3V using diodes.
Table 4.1 displays the signals which are routed from the SKE. Using the configuration discussed above, the information in table 4.1, a physical integration can
be made between the Beagleboard and the SKE. Figure 4.2 displays the physical
integration.
Signal
I2C_SDA
I2C_SCL
Codec mux
Din
Dout
Wclk
Bclk
Din
Dout
Wclk
Bclk
Description
I2C Serial Data
I2C Clock
Mux signal for selecting codec
Digital in to audio codec #1
Digital out from audio codec #1
Word clock to/from audio codec #1
Bit clock to/from audio codec #1
Digital in to audio codec #2
Digital out from audio codec #2
Word clock to/from audio codec #2
Bit clock to/from audio codec #2
Table 4.1. Integration signals from SKE
Section 4.2 will discuss how the expansion header configuration is done at the OS
Layer.
4.1 The Hardware Layer
Figure 4.2. Integration of SKE into expansion header of Beagleboard
19
20
Implementation of the RPCU
4.2
The OS Layer
At this stage we only have a physical interconnection between the SKE and Beagleboard. In order to make the Beagleboard communicate with the SKE, modifications has to be done at the OS Layer. As seen in 4.3 the modifications include:
• Redirecting the audio communication channels by modifying the ASoC.
• Configuration of the expansion header to allow usage of the McBSP channels,
I2C and GPIO.
Figure 4.3. The ASoC part of the overall design methodology
4.2.1
Configuring the Expansion Header
The Linux OMAP kernel provides architecture files that are general for all OMAP
processor platforms, but there are also files that are specific for each board. With
this method, a flexible solution is met were the board specific files exploits functionality from the general files which is needed for that specific board architecture.
The task of the board architecture files is to define and initiate the platform devices.
As we need to configure the expansion header, the Beagleboard architecture file
needs to be modified. The Beagleboard architecture file1 includes a multiplexer
terminator struct for configuring the expansion header. The multiplexer terminator can be seen in listing 4.1.
1 kernel/arch/arm/mach-omap2/board-omap3beagle.c
4.2 The OS Layer
21
Listing 4.1. OMAP mux terminator
#i f d e f CONFIG_OMAP_MUX
s t a t i c s t r u c t omap_board_mux board_mux [ ] __initdata = {
{ . r e g _ o f f s e t = OMAP_MUX_TERMINATOR } ,
};
#e n d i f
A general file that defines the available OMAP processor pins that can be multiplexed are found in the kernel file kernel/arch/arm/mach-omap2/mux34xx.h.
Using table 20 in [4] and the definitions of the signal names in mux34xx.h, the
configuration for allowing communication to the SKE can be seen in listing 4.2.
Listing 4.2. OMAP mux terminator configured for McBSP1, McBSP3
#i f d e f CONFIG_OMAP_MUX
s t a t i c s t r u c t omap_board_mux board_mux [ ] __initdata = {
OMAP3_MUX(UART2_CTS,OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT) ,
OMAP3_MUX(UART2_TX,OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT) ,
OMAP3_MUX(MCBSP3_FSX,OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT) ,
OMAP3_MUX(UART2_RTS,OMAP_MUX_MODE1 | OMAP_PIN_INPUT) ,
OMAP3_MUX(MCBSP1_DX,OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT) ,
OMAP3_MUX(MCBSP1_CLKX,OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT) ,
OMAP3_MUX(MCBSP1_FSX,OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT) ,
OMAP3_MUX(MCBSP1_DR,OMAP_MUX_MODE0 | OMAP_PIN_INPUT) ,
OMAP3_MUX(SDMMC2_DAT6,OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT) ,
OMAP3_MUX(I2C2_SDA ,OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP) ,
OMAP3_MUX( I2C2_SCL ,OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP) ,
{ . r e g _ o f f s e t = OMAP_MUX_TERMINATOR } ,
};
4.2.2
ALSA System on Chip
As mentioned in section 4.2, the ASOC specifies the connections between the audio
related components in the embedded system. Using a default ASoC configuration
for the Beagleboard would result in the on-chip TWL4030 codec still to be active.
In order to make the Beagleboard communicate with the SKE, the ASoC needs to
be reconfigured for the SKE audio codecs.
For the following sections, the reader is assumed to have basic knowledge of Linux
Device Drivers [5].
22
Implementation of the RPCU
4.2.2.1
Default ASoC Configuration for the Beagleboard
Inside the Linux OMAP kernel there are specific ASoC files for embedded systemon-chip processors using portable audio codecs.
Listing 4.3. Default hardware parameter settings
#i n c l u d e " . . / c o d e c s / t w l 4 0 3 0 . h "
s t a t i c i n t omap3beagle_hw_params (
s t r u c t snd_pcm_substream ∗ substream ,
s t r u c t snd_pcm_hw_params ∗ params )
{
s t r u c t snd_soc_pcm_runtime ∗ r t d = substream−>p r i v a t e _ d a t a ;
s t r u c t snd_soc_dai ∗ codec_dai = rtd−>dai−>codec_dai ;
s t r u c t snd_soc_dai ∗ cpu_dai = rtd−>dai−>cpu_dai ;
u n s i g n e d i n t fmt ;
int ret ;
s w i t c h ( params_channels ( params ) ) {
c a s e 2 : /∗ S t e r e o I2S mode ∗/
fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM;
break ;
c a s e 4 : /∗ Four c h a n n e l TDM mode ∗/
fmt = SND_SOC_DAIFMT_DSP_A |
SND_SOC_DAIFMT_IB_NF |
SND_SOC_DAIFMT_CBM_CFM;
break ;
default :
r e t u r n −EINVAL ;
}
The above function2 in listing 4.3 specifies the hardware operation parameters. An
important part of the ASoC is the DAI (digital audio interface) which specify the
operational parameters such as audio format3 that is set as either I2S (Inter-IC
sound) or four channel TDM (Time Division Multiplexed) mode. The rest of the
function, which can be seen in 7.7 sets the DAI configuration for both the CPU
and Codec.
2 All the code in this section is taken from the board architecture file for beagleboard: kernel/sound/soc/omap/omap3beagle.c
3 The different formats which are availabile can be found in kernel/include/sound/soc-dai.h
4.2 The OS Layer
23
Listing 4.4. Default DAI link
s t a t i c s t r u c t snd_soc_dai_link omap3beagle_dai = {
. name = "TWL4030 " ,
. stream_name = "TWL4030 " ,
. cpu_dai = &omap_mcbsp_dai [ 0 ] ,
. codec_dai = &twl4030_dai [ TWL4030_DAI_HIFI ] ,
. ops = &omap3beagle_ops ,
};
The code in listing 4.4, called ASoC glue, shows the DAI link omap3beagle_dai
which connects the CPU and audio codec. The CPU DAI is set to omap_mcbsp_dai[0],
which is an array, defining which DAI of the CPU the codec is bound to. The Linux
OMAP kernel provides device drivers for a large amount of portable audio codecs.
As can be seen in listing 4.4 the codec DAI is set to twl4030_dai[TWL4030_DAI_HIFI]
which is the device driver providing functionality for the codec DAI. The .ops parameter is set to omap3beagle_ops which are the hardware parameters defined in
listing 4.3.
Listing 4.5. Default Audio Machine Driver
s t a t i c s t r u c t snd_soc_card snd_soc_omap3beagle = {
. name = " omap3beagle " ,
. p l a t f o r m = &omap_soc_platform ,
. d a i _ l i n k = &omap3beagle_dai ,
. num_links = 1 ,
};
Listing 4.5 shows how the DAI link omap3beagle_dai is used to form the audio
machine driver for the OMAP platform. The num_links parameter tells us the
number of codecs which are bound to the DAI link.
Listing 4.6. Default Audio Subsystem
s t a t i c s t r u c t snd_soc_device omap3beagle_snd_devdata = {
. c a r d = &snd_soc_omap3beagle ,
. codec_dev = &soc_codec_dev_twl4030 ,
};
In listing 4.6, the audio machine driver defined in listing 4.5, is connected together
with the codec device driver specific parameter soc_codec_dev_twl4030 to form
the audio subsystem.
24
Implementation of the RPCU
Listing 4.7. Allocating the platform sound device and routing the cpu DAI to McBSP2
s t a t i c s t r u c t p l a t f o r m _ d e v i c e ∗ omap3beagle_snd_device ;
omap3beagle_snd_device =
p l a t f o r m _ d e v i c e _ a l l o c ( " soc−a u d i o " , −1);
i f ( ! omap3beagle_snd_device ) {
p r i n t k (KERN_ERR " P l a t f o r m d e v i c e a l l o c a t i o n f a i l e d \n " ) ;
r e t u r n −ENOMEM;
}
p l a t f o r m _ s e t _ d r v d a t a ( omap3beagle_snd_device ,
&omap3beagle_snd_devdata ) ;
omap3beagle_snd_devdata . dev = &omap3beagle_snd_device−>dev ;
∗ ( u n s i g n e d i n t ∗ ) omap3beagle_dai . cpu_dai−>p r i v a t e _ d a t a = 1 ;
In listing 4.7 the platform device for the sound device is defined. The sound device
is allocated with a platform specific parameter ’soc-audio” with the device ID =
-1. The parameter ”soc-audio” is a predefined parameter for the ASoC platform
driver defined in the ASoC core4 of the kernel. If the ID is set to -1, the kernel is
informed that there is only one instance of the device.
In the last line of code cpu_dai->private_data is set to 1. The integer defines
which of the McBSP channels the CPU DAI shall be routed to. Setting the integer
to 1 will route the CPU DAI to McBSP2, which is the standard McBSP channel
used for audio data in OMAP architectures.
4.2.2.2
Modifying the ASoC for the Beagleboard
The Beagleboard gives us the following prerequisites:
• The expansion header provides two McBSP channels, McBSP1 and McBSP3,
for integrating the two SKE audio codecs.
• The Linux OMAP kernel provides device drivers for the TLV320AIC31 audio
codec.
4 kernel/sound/soc/soc-core.c
4.2 The OS Layer
25
Listing 4.8. Modified DAI link
s t a t i c s t r u c t snd_soc_dai_link omap3beagle_dai [ ] = {
{
. name = " TLV320AIC3X " ,
. stream_name = "AIC3X " ,
. cpu_dai = &omap_mcbsp_dai [ 0 ] ,
. codec_dai = &aic3x_dai ,
. i n i t = omap3beagle_aic3x_init ,
. ops = &omap3beagle_ops ,
},
{
. name = " TLV320AIC3X " ,
. stream_name = "AIC3X " ,
. cpu_dai = &omap_mcbsp_dai [ 1 ] ,
. codec_dai = &aic3x_dai ,
. i n i t = omap3beagle_aic3x_init ,
. ops = &omap3beagle_ops ,
}
};
In listing 4.8 the DAI link has been expanded and modified to handle two TLV320AIC31
audio codecs5 . The codec DAI is set to aic3x, which is handled by the device driver
for the audio codec. A new parameter, init has been included, which is a driver
specific parameter for initializing the driver.
Listing 4.9. Modified Audio Machine Driver
s t a t i c s t r u c t snd_soc_card snd_soc_omap3beagle = {
. name = " omap3beagle " ,
. p l a t f o r m = &omap_soc_platform ,
. d a i _ l i n k = &omap3beagle_dai ,
. num_links = ARRAY_SIZE( omap3beagle_dai ) ,
};
Looking at the audio machine driver in listing 4.9, the num_links parameter has
been expanded to handle the size of the DAI link.
5 Observe
that the codecs have been routed to different CPU DAIs.
26
Implementation of the RPCU
Listing 4.10. Modified Audio Subsystem
s t a t i c s t r u c t aic3x_setup_data a i c 3 x _ s e t u p ;
s t a t i c s t r u c t snd_soc_device omap3beagle_snd_devdata = {
. c a r d = &snd_soc_omap3beagle ,
. codec_dev = &soc_codec_dev_aic3x ,
. codec_data = &aic3x_setup ,
};
The codec_dev parameter in the audio subsystem is modified for the TLV320AIC31
audio codec6 , see listing 4.10. A new parameter, codec_data has been included,
which is a driver specific parameter for setting up the codec.
As discussed in section 4.2.2.1, the final step connects the audio subsystem with
the platform sound device. The only modification done here is connecting the
DAI link to McBSP1 and McBSP3. Listing 4.11 shows how the two instances7 are
connected to the respective McBSP channels.
Listing 4.11. Route cpu DAI to McBSP1 and McBSP3
∗ ( u n s i g n e d i n t ∗ ) omap3beagle_dai [ 0 ] . cpu_dai−>p r i v a t e _ d a t a =0;
∗ ( u n s i g n e d i n t ∗ ) omap3beagle_dai [ 1 ] . cpu_dai−>p r i v a t e _ d a t a =2;
The board architecture file defines which devices that use I2C communication.
As previously mentioned in section 2.1, the TLV320AIC31 audio codec uses the
hardcoded I2C address 0x18. In listing 4.12, displaying the I2C definitions of the
board architecture file, the I2C information for the TLV320AIC31 audio is added.
6 soc_codec_dev_aic3x
s/tlv320aic3x.c
7 See listing 4.8
is
found
in
the
device
driver
file
kernel/sound/soc/codec-
4.2 The OS Layer
27
Listing 4.12. I2C initdata with added TLV320AIC31 addressing
s t a t i c s t r u c t i2c_board_info
__initdata b e a g l e _ i 2 c 1 _ b o a r d i n f o [ ] =
{
{
I2C_BOARD_INFO( " t l v 3 2 0 a i c 3 x " , 0 x18 ) ,
},
{
I2C_BOARD_INFO( " t w l 4 0 3 0 " , 0 x48 ) ,
. f l a g s = I2C_CLIENT_WAKE,
. i r q = INT_34XX_SYS_NIRQ,
. platform_data = &be a gl e _t w ld a ta ,
},
};
4.2.3
Building and Booting the modified Android sources
When building the kernel, architecture specific build files8 are used that are included9 in the Android sources. These build configuration files includes other configuration files called KConfigs that are needed for the architecture. The KConfigs
can in turn include other files that are needed.
Listing 4.13. KConfig part for OMAP Beagleboard
c o n f i g SND_OMAP_SOC_OMAP3_BEAGLE
t r i s t a t e " SoC Audio s u p p o r t f o r OMAP3 B e a g l e "
depends on TWL4030_CORE &&
SND_OMAP_SOC &&
MACH_OMAP3_BEAGLE
s e l e c t SND_OMAP_SOC_MCBSP
s e l e c t SND_SOC_TWL4030
help
Say Y i f you want t o add s u p p o r t
f o r SoC a u d i o on t h e B e a g l e b o a r d .
Listing 4.13 shows the default KConfig for the ASoC. As we can see the ASoC only
includes support for the TWL4030 audio codec. Thus using the default KConfig
for the ASoC, would result in no device drivers for the TLV320AIC31 audio codec
to be included in the build. Modifying the KConfigs for the ASoC, results in
the following configuration displayed in listing 4.14. The kernel contains a main
8 The
architecture specific files include settings and kernel includes into the build
9 kernel/arch/arm/configs
28
Implementation of the RPCU
configuration file for the Beagleboard10 . The main configuration file collects all the
information that shall be included in the build, for example all the KConfigs. Apart
from the KConfig for the ASoC, the main configuration file contains functionality
for supporting the TWL4030 audio codec. This functionality is replaced to support
the TLV320AIC31 audio codec.
Listing 4.14. Modified KConfig part for OMAP Beagleboard
c o n f i g SND_OMAP_SOC_OMAP3_BEAGLE
t r i s t a t e " SoC Audio s u p p o r t f o r OMAP3 B e a g l e "
depends on I2C &&
SND_OMAP_SOC &&
MACH_OMAP3_BEAGLE
s e l e c t SND_OMAP_SOC_MCBSP
s e l e c t SND_SOC_TLV320AIC3X
help
Say Y i f you want t o add s u p p o r t
f o r SoC a u d i o on t h e B e a g l e b o a r d .
When the kernel is modified, it is time to build11 it. Figure 4.4 shows a print
taken at boot-up, displaying the ASoC audio codec mappings.
Figure 4.4. Kernel print for ASoC part when booting Android with the modified Kernel
10 kernel/arch/arm/configs/omap3_beagle_android_defconfig
11 See
[9] for build instructions.
4.3 The Application Layer
4.3
29
The Application Layer
The last step in the implementation is to develop an application running the SKE
audio processing functionality, see figure 4.5. The application is developed using
the framework GStreamer, that utilizes ALSA to communicate with the SKE audio
codecs.
Figure 4.5. The GStreamer SKE Application part of the overall design methodology
4.3.1
GStreamer SKE Application
GStreamer uses so called processing elements, connected together to form a pipeline.
As audio flows through the pipeline, it is manipulated depending on the element
settings. To provide an example, a simple pipeline may consist of a volume and a
balance element.
A pipeline starts with a source pad element, which is connected tp the audio
module of the operating system, in this case ALSA. A pipeline ends with a sink
pad element, which is also connected to the audio module of the operating system.
The pipelined design makes it easy to add more elements if there is need for more
functionality.
The SKE application pipeline is explained below. An overview of the pipeline is
also provided in figure 4.6.
• source: the source consists of an alsasrc element. The alsasrc element takes
audio input from the ALSA module of the operating system.
• audioconv: the audioconv element is used to convert audio streams to a raw
audio data format.
• audioresample: a legacyresample element that is used to resample raw audio
data to a desired format controlled by the next element in the pipeline.
30
Implementation of the RPCU
• capsfilter: the capsfilter element does not modify the data but enforces limitations on the data format. The capsfilter element is used for controlling
the number of audio channels (mono or stereo).
• audiobalance: an audiopanorama element that makes it possible to balance
the audio between two audio channels (left or right).
• volume: the volume element controls the audio volume. The element also
provides functionality of muting the audio channels.
• sink: the sink consists of a alsasink element. The alsasink element takes
audio input from the previous element and outputs it to the ALSA module
of the operating system.
Figure 4.6. Overview of the pipeline configuration. The above picture displays the
pipeline in stereo mode whereas the below one displays the pipeline in mono mode.
GStreamer also provides functions for setting up and controlling the pipeline. The
functions used for the SKE application are described below.
static gboolean bus_call
This function sets up a handler for bus errors. If an error occurs, it catches the
error message, displays it in the terminal and then terminates the program.
void pipe_setup
This function creates, adds and links together the elements that are in the pipeline.
gboolean command_callback
This function is used to control the program. The function listens to input characters and changes the functionality of the pipeline. The change in functionality
is done by changing properties in the elements or by creating a new pipeline with
different elements. Currently the following characters are used:
q
quits the program by exiting the main loop.
m
mutes or unmutes the sound by setting the mute parameter in the volume
element.
4.3 The Application Layer
+
increases the sound volume.
-
decrease the sound volume.
r
pans the sound to the right.
l
pans the sound to the left.
c
starts the configuration handler.
t
sets up two sound channels for stereo sound.
o
sets up one sound channel for mono sound.
31
int main
The main function initializes the pipeline by setting up pipeline parameters and
calling pipe_setup. After setting up the pipeline and its parameters, the function
activates the SKE application by entering the main loop. If the user quits, the
pipeline is cleaned and terminated.
4.3.2
Configuration Handling Application
The SKE is configurable for a wide range of different communication equipment.
This functionality must also be supported by the RPCS.
In this section, a concept for a basic configuration tool is presented that acts with
the SKE application. The configuration tool discussed in this section is designed
to work through a Linux terminal, thus it is not intended to be used in the endproduct. The intention is to provide visualization to the customer of how the
configuration tool may be designed to act with the SKE application. Figure 4.7
shows the architecture and environment of the configuration handling module.
Figure 4.7. The architecture of the basic configuration tool
32
Implementation of the RPCU
At first the SKE application creates an empty pipeline and invokes the configuration handling module. This can be seen in the first two states in figure 4.8.
Figure 4.8. State machine description of Configuration handling together with
GStreamer application
At this stage the configuration menu displayed in figure 4.9, is shown to the user.
Figure 4.9. The configuration menu
If the user presses ”H”, the menu in figure 4.10 appears. The current headset
configuration is shown together with the headset configurations available. The user
is asked to select a headset configuration to be loaded. As the user has selected a
configuration, the program returns to the menu. Note that the configurations are
only loaded, the configuration parameters are not set until the user presses ”L” in
the main menu. This is a mechanism for protecting the user from loading wrong
configurations by mistake.
4.3 The Application Layer
33
When the configurations are loaded and set, the parameters in the configuration
files are loaded into the operational parameters used by the SKE application. The
pipeline of the SKE application is initialized and set to playing state. The configuration handling module is invoked if the user interrupts the pipeline by pressing
the key ”c”. The pipeline will then be paused and the configuration routine starts
from the beginning.
Figure 4.10. Configuration of headset
Chapter 5
Verification
Since the focus of this thesis is design of a prototype, the verification effort is spent
on functionality rather than requirements. The following questions were used as
a guideline for verifying the functionality.
Does the chosen hardware integration work at the physical level?
We did not get this part of the integration to work as intended. The SKE was
chosen as the candidate for fulfilling the needs for additional audio interfaces.
After modification, the SKE PCB card turned to be very fragille which made it
very hard to verify and troubleshoot this part. There are many parts that can
contribute to the faulty behavior. Components may have been damaged or bridging/connectivity problems may have occurred during the modification of the PCB
card.
Does the ASoC and Beagleboard expansion header configuration behave correctly
after modification?
In the boot-up printout we can clearly see that the operating system recognizes
the modifications in the AsoC. Although it is very hard to verify this part due
to the problems with the physical integration of the SKE. Figure 4.4 shows that
a mapping has been done between the TLV320AIC31 audio codecs to the corresponding McBSP channels, but at the same time no device is found. It is also hard
to verify if the configuration of the expansion header has been made correctly. No
other test stimuli could be provided than when integrated with the SKE, which
made it almost impossible due to the failing SKE.
Does the GStreamer application fulfill the needs of the SKE audio processing functionality?
The GStreamer application proves to be a good candidate for fulfilling the needs of
the SKE audio processing functionality. GStreamer also provides good expansion
35
36
Verification
possibilities for adding more functionality. Fundamental parts of the audio processing functionality was implemented during this thesis such as volume control,
channel control, balance control etc.
Does the entire integration chain work?
The failing link in the chain proved to be the integration at the physical layer.
The modified SKE proved to be very fragile. The ball-point connections of the
components, which were modified on the SKE PCB card, got loose when touched.
A complete integration verification could not be done due to the problems with
the SKE.
Chapter 6
Conclusion
Before the RPCU thesis was formed, Saab AB had the vision of implementing a
complete prototype of the entire RPCS in one thesis (a complete integration of
the four sub-systems). In the beginning, the only directive given was the outline
in figure 1.1. Beside from the outline, the SKE audio processing functionality was
to be preserved into an embedded processor based platform.
A natural and critical step was to apply a requirements elicitation to get a more
formal picture of how the RPCS was to be implemented. This also gave us the
opportunity to decide which parts were to be prioritized. The requirements elicitation proved that a complete implementation of RPCS was way to large for the
given time. The agreement with Saab AB was that the thesis was to be focused
on implementing a prototype of the RPCU subsystem.
Focusing on the requirements elicitation for the RPCU sub-system, an important
part was to include Saab AB in the process. Applying the methods discussed in
section 2.2 (Adaptability, Maturity and Priority) and iterating the requirement
elicitation with Saab AB, gave a clearer picture of what should be achieved in this
thesis.
Given the requirements for the RPCU and which priority each requirement had,
the next step was to make a system design for the RPCU. When selecting the
appropriate hardware, the choice fell on Beagleboard due to the wide range of
different open source projects. There is also knowledge of working with similar
hardware platforms within Saab AB. Reusing the SKE, takes aspects such as economy and reusability into account.
The intention of a layered design was to give a good abstraction between hardware
and software. Using the SKE and Beagleboard resulted in a physical integration
work at the hardware layer. Making custom soundcard, instead of reusing the
SKE, would have taken too much time. At the OS Layer, a configuration of the
Beagleboard expansion header interface was needed to make audio data commu37
38
Conclusion
nication (McBSP) possible. A modification of the ASoC was also needed to make
the Beagleboard recognize the TLV320AIC31 audio codecs. At last, GStreamer
was chosen as the framework for implementing the SKE audio processing functionality. GStreamer was chosen due to the great possibilities of supporting different
audio processing functions.
Although we did not get the integration fully verified, the design methodology and
following implementation provided a good basis for future development. In order
to completely verify the work that has been done at the OS Layer, work has to
be done at the Hardware Layer. Either a redesigned SKE has to be made to gain
a more reliable point-to-point connection with the Beagleboard, or developing a
custom soundcard with additional audio interfaces.
Before integrating the expansion header, deterministic test stimuli behaving as the
integrated unit should be provided, in order to verify that the expansion header
configuration and ASoC behaves correctly. With these methods, a more effective
integration and following verification can be achieved.
As commonly proven, verifying and validating integration on different levels are
very complex, especially when testing is not included in the design process. As
neither one of us had former knowledge in working with Android and the Linux
Kernel, it was hard to identify a good approach and method for testing the implementation.
Summarized, this thesis provides a design proposal and a way of implementing
an embedded system intended for handling audio and audio processing. In order
to proceed, a more structured verification and validation plan has to be made in
conjunction with the implementation.
Chapter 7
Appendices
7.1
GStreamer application code, header file gst_ske.h
#include
#include
#include
#include
#include
#include
#include
<gst/gst.h>
<stdbool.h>
<glib.h>
<stdio.h>
<stdlib.h>
<string.h>
<ctype.h>
static GMainLoop *loop;
GstElement
GstElement
GstElement
GstElement
GstElement
GstElement
GstElement
GstElement
GstElement
GstElement
*pipeline;
*source;
*sink;
*audioconv;
*audioresample;
*audiobalance;
*volume;
*capsfilter;
*audiocx;
*capsfilter_2;
GstBus *bus;
gchar *read;
GIOChannel *channel;
gboolean *mute;
gint chan;
int fd[2];
float maxvol;
39
40
Appendices
float
float
float
float
minvol;
med;
vol;
balance;
static gboolean bus_call(GstBus *bus, GstMessage *msg, void *user_data);
void pipe_setup();
gboolean command_callback(GIOChannel *source,GIOCondition condition,
gpointer data);
7.2
GStreamer application code, body file gst_ske.c
#include "gst_ske.h"
#include "config.h"
/* Setup a bus for error messages */
static gboolean bus_call(GstBus *bus, GstMessage *msg, void *user_data)
{
switch (GST_MESSAGE_TYPE(msg)) {
case GST_MESSAGE_EOS: {
g_message("End-of-stream");
g_main_loop_quit(loop);
break;
}
case GST_MESSAGE_ERROR: {
GError *err;
gst_message_parse_error(msg, &err, NULL);
g_error("%s", err->message);
g_error_free(err);
g_main_loop_quit(loop);
break;
}
default:
break;
}
return true;
}
/* Setup a the pipeline
void pipe_setup()
{
*/
7.2 GStreamer application code, body file gst_ske.c
41
/* Create elements */
pipeline = gst_pipeline_new ("audio-player");
source
= gst_element_factory_make ("alsasrc" ,"alsa-source");
audioconv
= gst_element_factory_make ("audioconvert","convert");
audioresample
= gst_element_factory_make ("legacyresample",NULL);
audiobalance
= gst_element_factory_make ("audiopanorama","audio_bal");
volume
= gst_element_factory_make ("volume","volume");
sink
= gst_element_factory_make ("alsasink","audio-output");
audiocx
= gst_element_factory_make ("audioconvert","convert");
/* Print error messages if failed to create element */
if (!pipeline || !source || !audioconv || !audioresample || !audiobalance
g_printerr ("One element could not be created. Exiting.\n");
return -1;
}
/* Create structure for stereo or mono sound */
capsfilter = gst_element_factory_make("capsfilter", NULL);
GstCaps *caps = gst_caps_new_empty();
GstStructure *cs;
cs = gst_structure_new("audio/x-raw-int","channels", G_TYPE_INT, chan, NULL);
gst_caps_append_structure(caps, cs);
g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL);
gst_caps_unref(caps);
/* Set the input filename to the source element */
g_object_set (G_OBJECT (source), "device","hw:0" , NULL);
g_object_set (G_OBJECT (volume), "mute",FALSE , NULL);
g_object_set (G_OBJECT (volume), "volume",vol , NULL);
g_object_set (G_OBJECT (sink), "sync",FALSE , NULL);
g_object_set (G_OBJECT (audiobalance), "panorama",balance , NULL);
/* If mono don’t add audiobalance */
if(chan==1){
/* Add all elements into the pipeline */
/* file-source | alsa-output */
gst_bin_add_many (GST_BIN (pipeline),
source, audioconv, audioresample, capsfilter, volume, sink, NULL);
/* Link the elements together */
/* file-source -> alsa-output */
gst_element_link_many (source, audioconv, audioresample,
capsfilter, volume, sink, NULL);
}
|
42
Appendices
else {
/* Add all elements into the pipeline */
/* file-source | alsa-output */
gst_bin_add_many (GST_BIN (pipeline),
source, audioconv, audioresample, capsfilter,
audiobalance, volume, sink, NULL);
/* Link the elements together */
/* file-source -> alsa-output */
gst_element_link_many (source, audioconv,
audiobalance, volume, sink, NULL);
audioresample, capsfilter,
}
}
/* Callback function to control the pipeline
gboolean command_callback(GIOChannel *source,
GIOCondition condition,gpointer data)
{
/* Get command */
char cmd;
g_print("cmd = ");
cmd = getchar();
g_print("",cmd);
switch(cmd){
*/
/* Quit */
case ’q’:
g_main_loop_quit((GMainLoop *)data);
return FALSE;
break;
/* Mute or unmute */
case ’m’:
if(mute){
g_object_set (G_OBJECT (volume),
gst_element_set_state (pipeline,
mute = FALSE;
return TRUE;
break;
}
else{
g_object_set (G_OBJECT (volume),
gst_element_set_state (pipeline,
mute = TRUE;
return TRUE;
break;
"mute",FALSE , NULL);
GST_STATE_PLAYING);
"mute",TRUE , NULL);
GST_STATE_PLAYING);
7.2 GStreamer application code, body file gst_ske.c
43
}
/* Increase volume */
case ’+’:
if(vol <= maxvol)
vol=vol+0.1;
g_object_set (G_OBJECT (volume), "volume",vol , NULL);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
return TRUE;
break;
/* Lower volume */
case ’-’:
if(vol >= minvol)
vol=vol-0.1;
g_object_set (G_OBJECT (volume), "volume",vol , NULL);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
return TRUE;
break;
/* Balance audio right */
case ’r’:
balance=balance+0.1;
g_object_set (G_OBJECT (audiobalance), "panorama",balance , NULL);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
return TRUE;
break;
/* Balance audio left */
case ’l’:
balance=balance-0.1;
g_object_set (G_OBJECT (audiobalance), "panorama",balance , NULL);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
return TRUE;
break;
/* Configure */
case ’c’:
gst_element_set_state (pipeline, GST_STATE_PAUSED);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
FLUSH;
configure();
balance=0;
pipe_setup();
gst_element_set_state (pipeline, GST_STATE_READY);
44
Appendices
g_object_set (G_OBJECT (volume), "volume",((maxvol-minvol)/2) , NULL);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
return TRUE;
break;
/* Stereo sound */
case ’t’:
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
chan=2;
pipe_setup();
gst_element_set_state (pipeline, GST_STATE_READY);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
return TRUE;
/* Mono sound */
case ’o’:
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
chan=1;
pipe_setup();
gst_element_set_state (pipeline, GST_STATE_READY);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
return TRUE;
/* Just continue running main loop
default:
return TRUE;
}
}
*/
int main(int argc, char *argv[])
{
/* Initialisation */
gst_init (NULL, NULL);
configure();
balance=0;
channel = g_io_channel_unix_new(fd[0]);
loop = g_main_loop_new (NULL, FALSE);
pipe_setup();
g_object_set (G_OBJECT (volume), "volume",((maxvol-minvol)/2) , NULL);
/* Add a message handler */
7.3 Configuration handling code, header file config.h
45
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
/* Set the pipeline to "playing" state*/
g_print ("Now playing: alsasrc \n");
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* Add watch */
g_io_add_watch(channel,G_IO_IN | G_IO_HUP | G_IO_ERR,command_callback,loop);
/* Iterate */
g_print ("Running...\n");
g_main_loop_run (loop);
/* Out of the main loop, clean up nicely */
g_print ("Returned, stopping playback\n");
g_io_channel_shutdown(channel,TRUE,NULL);
gst_element_set_state (pipeline, GST_STATE_NULL);
g_print ("Deleting pipeline\n");
gst_object_unref (GST_OBJECT (pipeline));
return 0;
}
7.3
Configuration handling code, header file config.h
#include
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<string.h>
<ctype.h>
<glob.h>
#define FLUSH
while(getchar() != ’\n’ && getchar() != EOF)
#define HSDIR "configs/headset/*.*"
#define RDIR "configs/radio/*.*"
#define IDIR "configs/intercom/*.*"
#define HSCONF "M2795-879010.txt"
#define RCONF "RA1031.txt"
46
Appendices
#define ICONF "LTS90-100.txt"
static char hsfile[20] = HSCONF;
static char rfile[20] = RCONF;
static char ifile[20] = ICONF;
int set_config(char* file);
char *load_config(char *dir);
void
void
void
void
7.4
print_menu();
menu();
setparam(char *str, int size, FILE *fp);
configure();
Configuration handling code, body file config.c
#include "helpers.h"
#include "config.h"
#include "gst_ske.h"
char *load_config(char *dir)
{
char input;
glob_t data;
char subdir[20];
static char files[10][20];
switch( glob(dir, 0, NULL, &data ) )
{
case 0:
break;
case GLOB_NOSPACE:
printf( "Out of memory\n" );
break;
case GLOB_ABORTED:
printf( "Reading error\n" );
break;
case GLOB_NOMATCH:
printf( "No files found\n" );
break;
default:
break;
}
7.4 Configuration handling code, body file config.c
47
strcpy(subdir, replace_str(dir, "*.*", ""));
printf("ID CONFIGURATION\n");
printf("--------------------------------\n");
int i;
for(i=0; i<data.gl_pathc; i++)
{
strcpy(files[i], replace_str(data.gl_pathv[i], subdir, ""));
printf("%d) ", i); printf("%s\n", replace_str(files[i], ".txt", ""));
}
printf("\n");
printf("Type configuration ID to be set: ");
scanf("%c", &input);
FLUSH;
printf("\n");
if(isalpha(input))
printf("Not a numeric value!");
else if(atoi(&input) > i || atoi(&input) < 0)
printf("No such configuration ID!");
return files[atoi(&input)];
globfree( &data );
}
void print_menu()
{
printf("\n");
printf("MAIN - RPCS CONFIGURATION\n");
printf("--------------------------------\n");
printf("H: Headset Configuration\n");
printf("R: Radio Configuration\n");
printf("I: Intercom Configuration\n");
printf("P: Print Configuration\n");
printf("D: Reset Configuration (Default)\n");
printf("L: Load settings & Quit\n");
printf("Q: Quit without changes\n");
printf("--------------------------------\n\n");
}
void menu()
{
48
Appendices
int input;
int i;
do
{
print_menu();
printf(">");
input = getchar();
FLUSH;
printf("\n");
switch(input)
{
case ’H’:
printf("Current headset configuration: ");
printf("%s\n\n", replace_str(hsfile, ".txt", ""));
strcpy(hsfile, load_config(HSDIR));
break;
case ’R’:
printf("current radio configuration: ");
printf("%s\n\n", replace_str(rfile, ".txt", ""));
strcpy(rfile, load_config(RDIR));
break;
case ’I’:
printf("current intercom configuration: ");
printf("%s\n\n", replace_str(ifile, ".txt", ""));
strcpy(ifile, load_config(IDIR));
break;
case ’D’:
printf("Configuration data will be reset to default? y=yes n=no: ");
input = getchar();
FLUSH;
if(input == ’y’)
{
strcpy(hsfile, HSCONF);
strcpy(rfile, RCONF);
strcpy(ifile, ICONF);
printf("\n");
printf("DEFAULT CONFIGURATION SET!\n");
}
else if(input == ’n’)
break;
else
printf("invalid argument, aborting!\n");
break;
7.4 Configuration handling code, body file config.c
case ’P’:
printf("CURRENT CONFIGURATION:\n");
printf("--------------------------------\n");
printf("Headset: ");
printf("%s\n", replace_str(hsfile, ".txt", ""));
printf("Radio:
");
printf("%s\n", replace_str(rfile, ".txt", ""));
printf("Intercom: ");
printf("%s\n", replace_str(ifile, ".txt", ""));
break;
case ’L’:
input = ’Q’;
break;
case ’Q’:
strcpy(hsfile, HSCONF);
strcpy(rfile, RCONF);
strcpy(ifile, ICONF);
break;
default:
printf("Not a command!\n");
}
} while(input != ’Q’);
}
void setparam(char *str, int size, FILE *fp)
{
if(strcmp("MAX_VOLUME_GAIN",str) == 0)
{
fgets(str, size, fp);
strip_newline(str, size);
maxvol = atof(str);
}
else if(strcmp("MIN_VOLUME_GAIN",str) == 0)
{
fgets(str, size, fp);
strip_newline(str, size);
minvol = atof(str);
}
else if(strcmp("STEREO",str) == 0)
{
fgets(str, size, fp);
strip_newline(str, size);
chan = atoi(str);
}
}
49
50
Appendices
int set_config(char* file)
{
FILE *cfp;
char pbuf[20];
printf("%s\n", file);
cfp = fopen(file, "r");
if(cfp == NULL)
{
printf("File could not be opened");
return 0;
}
while(fgets(pbuf, sizeof(pbuf), cfp) != NULL)
{
strip_newline(pbuf, sizeof(pbuf));
setparam(pbuf, sizeof(pbuf), cfp);
}
fclose(cfp);
return 1;
}
void configure()
{
char filedir[64];
menu();
strcpy(filedir, replace_str(HSDIR, "*.*", ""));
strcat(filedir, hsfile);
set_config(filedir);
strcpy(filedir, replace_str(RDIR, "*.*", ""));
strcat(filedir, rfile);
set_config(filedir);
strcpy(filedir, replace_str(IDIR, "*.*", ""));
strcat(filedir, ifile);
set_config(filedir);
}
7.5
Help functions code, header file helpers.h
#ifndef HELPERS_H_GUARD
7.6 Help functions code, header file helpers.c
#define HELPERS_H_GUARD
void strip_newline(char *str, int size);
char *replace_str(char *str, char *orig, char *rep);
#endif
7.6
Help functions code, header file helpers.c
#include "helpers.h"
void strip_newline( char *str, int size )
{
int i;
for ( i = 0; i < size; ++i )
{
if ( str[i] == ’\n’ )
{
str[i] = ’\0’;
return;
}
}
}
char *replace_str(char *str, char *orig, char *rep)
{
static char buffer[4096];
char *p;
if(!(p = strstr(str, orig)))
return str;
// Is ’orig’ even in ’str’?
// Copy characters from ’str’ start to ’orig’ st$
strncpy(buffer, str, p-str);
buffer[p-str] = ’\0’;
sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));
return buffer;
}
7.7
Modified code for omap3beagle.c
/*
* omap3beagle.c
--
SoC audio for OMAP3 Beagle
51
52
Appendices
*
* Author: Steve Sakoman <[email protected]>
*
* 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.
*
* This program is distributed in the hope that 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<linux/clk.h>
<linux/platform_device.h>
<linux/module.h>
<linux/moduleparam.h>
<linux/timer.h>
<linux/interrupt.h>
<sound/core.h>
<sound/pcm.h>
<sound/soc.h>
<sound/soc-dapm.h>
<linux/i2c.h>
#include
#include
#include
#include
<asm/mach-types.h>
<mach/hardware.h>
<mach/gpio.h>
<plat/mcbsp.h>
#include
#include
#include
#include
"omap-mcbsp.h"
"omap-pcm.h"
"../codecs/twl4030.h"
"../codecs/tlv320aic3x.h"
static
struct
{
struct
struct
int omap3beagle_hw_params(struct snd_pcm_substream *substream,
snd_pcm_hw_params *params)
snd_soc_pcm_runtime *rtd = substream->private_data;
snd_soc_dai *codec_dai = rtd->dai->codec_dai;
7.7 Modified code for omap3beagle.c
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
unsigned int fmt;
int ret;
switch (params_channels(params)) {
case 2: /* Stereo I2S mode */
fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM;
break;
case 4: /* Four channel TDM mode */
fmt = SND_SOC_DAIFMT_DSP_A |
SND_SOC_DAIFMT_IB_NF |
SND_SOC_DAIFMT_CBM_CFM;
break;
default:
return -EINVAL;
}
/* Set codec DAI configuration */
ret = snd_soc_dai_set_fmt(codec_dai, fmt);
if (ret < 0) {
printk(KERN_ERR "can’t set codec DAI configuration\n");
return ret;
}
/* Set cpu DAI configuration */
ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
if (ret < 0) {
printk(KERN_ERR "can’t set cpu DAI configuration\n");
return ret;
}
/* Vi har en extern MCLK, behövs denna? */
/* Set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 19200000,
SND_SOC_CLOCK_IN);
if (ret < 0) {
printk(KERN_ERR "can’t set codec system clock\n");
return ret;
}
return 0;
}
53
54
Appendices
static struct snd_soc_ops omap3beagle_ops = {
.hw_params = omap3beagle_hw_params,
};
static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_LINE("Line In", NULL),
};
static const struct snd_soc_dapm_route audio_map[] = {
/* Headphone connected to LLOUT, LROUT */
{"Headphone Jack", NULL, "LLOUT"},
{"Headphone Jack", NULL, "LROUT"},
/* Line In
{"LINE1L",
{"LINE2L",
{"LINE1R",
{"LINE2R",
};
connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
NULL, "Line In"},
NULL, "Line In"},
NULL, "Line In"},
NULL, "Line In"},
static int omap3beagle_aic3x_init(struct snd_soc_codec *codec)
{
/* Add beagle specific widgets */
snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
ARRAY_SIZE(aic3x_dapm_widgets));
/* Set up beagle specific audio path audio_map */
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
/* not connected */
snd_soc_dapm_disable_pin(codec,
snd_soc_dapm_disable_pin(codec,
snd_soc_dapm_disable_pin(codec,
snd_soc_dapm_disable_pin(codec,
snd_soc_dapm_disable_pin(codec,
"MONO_LOUT");
"HPLCOM");
"HPRCOM");
"HPLOUT");
"HPROUT");
/* always connected */
snd_soc_dapm_enable_pin(codec, "Headphone Jack");
snd_soc_dapm_enable_pin(codec, "Line In");
snd_soc_dapm_sync(codec);
return 0;
}
7.7 Modified code for omap3beagle.c
55
/* Digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link omap3beagle_dai[] = {
{
.name = "TLV320AIC3X",
.stream_name = "AIC3X",
.cpu_dai = &omap_mcbsp_dai[0],
.codec_dai = &aic3x_dai,
.init = omap3beagle_aic3x_init,
.ops = &omap3beagle_ops,
},
{
.name = "TLV320AIC3X",
.stream_name = "AIC3X",
.cpu_dai = &omap_mcbsp_dai[1],
.codec_dai = &aic3x_dai,
.init = omap3beagle_aic3x_init,
.ops = &omap3beagle_ops,
},
};
/* Audio machine driver */
static struct snd_soc_card snd_soc_omap3beagle = {
.name = "omap3beagle",
.platform = &omap_soc_platform,
.dai_link = omap3beagle_dai, /* Adressera dà det bara Ãr en link */
.num_links = ARRAY_SIZE(omap3beagle_dai),
};
static struct aic3x_setup_data aic3x_setup;
/* Audio subsystem */
static struct snd_soc_device omap3beagle_snd_devdata = {
.card = &snd_soc_omap3beagle,
.codec_dev = &soc_codec_dev_aic3x,
.codec_data = &aic3x_setup,
};
static struct platform_device *omap3beagle_snd_device;
static int __init omap3beagle_soc_init(void)
{
int ret;
if (!machine_is_omap3_beagle()) {
pr_debug("Not OMAP3 Beagle!\n");
return -ENODEV;
56
Appendices
}
pr_info("OMAP3 Beagle SoC init\n");
omap3beagle_snd_device = platform_device_alloc("soc-audio", -1);
if (!omap3beagle_snd_device) {
printk(KERN_ERR "Platform device allocation failed\n");
return -ENOMEM;
}
platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata);
omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev;
*(unsigned int *)omap3beagle_dai[0].cpu_dai->private_data = 0; /* McBSP1 */
*(unsigned int *)omap3beagle_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
ret = platform_device_add(omap3beagle_snd_device);
if (ret)
goto err1;
return 0;
err1:
printk(KERN_ERR "Unable to add platform device\n");
platform_device_put(omap3beagle_snd_device);
return ret;
}
static void __exit omap3beagle_soc_exit(void)
{
platform_device_unregister(omap3beagle_snd_device);
}
module_init(omap3beagle_soc_init);
module_exit(omap3beagle_soc_exit);
MODULE_AUTHOR("Steve Sakoman <[email protected]>");
MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle");
MODULE_LICENSE("GPL");
7.8
Modified code for board-omap3beagle.c
/*
* linux/arch/arm/mach-omap2/board-omap3beagle.c
*
* Copyright (C) 2008 Texas Instruments
7.8 Modified code for board-omap3beagle.c
57
*
* Modified from mach-omap2/board-3430sdp.c
*
* Initial code: Syed Mohammed Khasim
*
* 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<linux/kernel.h>
<linux/init.h>
<linux/platform_device.h>
<linux/delay.h>
<linux/err.h>
<linux/clk.h>
<linux/io.h>
<linux/leds.h>
<linux/gpio.h>
<linux/irq.h>
<linux/input.h>
<linux/gpio_keys.h>
<linux/usb/android_composite.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <linux/regulator/machine.h>
#include <linux/i2c/twl.h>
#include
#include
#include
#include
#include
<mach/hardware.h>
<asm/mach-types.h>
<asm/mach/arch.h>
<asm/mach/map.h>
<asm/mach/flash.h>
#include
#include
#include
#include
#include
#include
#include
#include
#include
<plat/board.h>
<plat/common.h>
<plat/display.h>
<plat/gpmc.h>
<plat/nand.h>
<plat/usb.h>
<plat/timer-gp.h>
<plat/clock.h>
<plat/omap-pm.h>
58
Appendices
#include
#include
#include
#include
#ifdef
static
static
static
static
static
static
#else
static
static
static
static
static
static
#endif
"mux.h"
"mmc-twl4030.h"
"pm.h"
"omap3-opp.h"
CONFIG_PM
struct omap_opp *
struct omap_opp *
struct omap_opp *
struct omap_opp *
struct omap_opp *
struct omap_opp *
/* CONFIG_PM */
struct omap_opp *
struct omap_opp *
struct omap_opp *
struct omap_opp *
struct omap_opp *
struct omap_opp *
/* CONFIG_PM */
_omap35x_mpu_rate_table = omap35x_mpu_rate_table;
_omap37x_mpu_rate_table = omap37x_mpu_rate_table;
_omap35x_dsp_rate_table = omap35x_dsp_rate_table;
_omap37x_dsp_rate_table = omap37x_dsp_rate_table;
_omap35x_l3_rate_table = omap35x_l3_rate_table;
_omap37x_l3_rate_table = omap37x_l3_rate_table;
_omap35x_mpu_rate_table = NULL;
_omap37x_mpu_rate_table = NULL;
_omap35x_dsp_rate_table = NULL;
_omap37x_dsp_rate_table = NULL;
_omap35x_l3_rate_table = NULL;
_omap37x_l3_rate_table = NULL;
#if defined(CONFIG_VIDEO_MT9V113) || defined(CONFIG_VIDEO_MT9V113_MODULE)
#include <media/v4l2-int-device.h>
#include <media/mt9v113.h>
extern struct mt9v113_platform_data mt9v113_pdata;
#endif
#if defined(CONFIG_VIDEO_MT9T112) || defined(CONFIG_VIDEO_MT9T112_MODULE)
#include <media/v4l2-int-device.h>
#include <media/mt9t112.h>
extern struct mt9t112_platform_data mt9t112_pdata;
#endif
#define GPMC_CS0_BASE
#define GPMC_CS_SIZE
0x60
0x30
#define NAND_BLOCK_SIZE SZ_128K
extern struct regulator_consumer_supply twl4030_vmmc1_supply;
extern struct regulator_consumer_supply twl4030_vsim_supply;
extern struct regulator_init_data vmmc1_data;
extern struct regulator_init_data vsim_data;
#ifdef CONFIG_USB_ANDROID
7.8 Modified code for board-omap3beagle.c
#define GOOGLE_VENDOR_ID 0x18d1
#define GOOGLE_PRODUCT_ID 0x9018
#define GOOGLE_ADB_PRODUCT_ID 0x9015
static char *usb_functions_adb[] = {
"adb",
};
static char *usb_functions_all[] = {
"adb",
};
static struct android_usb_product usb_products[] = {
{
.product_id = GOOGLE_PRODUCT_ID,
.num_functions = ARRAY_SIZE(usb_functions_adb),
.functions = usb_functions_adb,
},
};
static struct android_usb_platform_data android_usb_pdata = {
.vendor_id = GOOGLE_VENDOR_ID,
.product_id = GOOGLE_PRODUCT_ID,
.functions = usb_functions_all,
.products = usb_products,
.version = 0x0100,
.product_name = "rowboat gadget",
.manufacturer_name = "rowboat",
.serial_number = "20100720",
.num_functions = ARRAY_SIZE(usb_functions_all),
};
static struct platform_device androidusb_device = {
.name = "android_usb",
.id = -1,
.dev = {
.platform_data = &android_usb_pdata,
},
};
static void omap3evm_android_gadget_init(void)
{
platform_device_register(&androidusb_device);
}
59
60
Appendices
#endif
char expansionboard_name[16];
#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
#include <plat/mcspi.h>
#include <linux/spi/spi.h>
#define OMAP3BEAGLE_GPIO_ENC28J60_IRQ 157
static struct omap2_mcspi_device_config enc28j60_spi_chip_info = {
.turbo_mode = 0,
.single_channel = 1,/* 0: slave, 1: master */
};
static struct spi_board_info
omap3beagle_zippy_spi_board_info[] __initdata = {
{
.modalias = "enc28j60",
.bus_num = 4,
.chip_select = 0,
.max_speed_hz = 20000000,
.controller_data = &enc28j60_spi_chip_info,
},
};
static void __init omap3beagle_enc28j60_init(void)
{
if ((gpio_request(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, "ENC28J60_IRQ") == 0) &&
(gpio_direction_input(OMAP3BEAGLE_GPIO_ENC28J60_IRQ) == 0)) {
gpio_export(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, 0);
omap3beagle_zippy_spi_board_info[0].irq =
OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_ENC28J60_IRQ);
set_irq_type(omap3beagle_zippy_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
} else {
printk(KERN_ERR "could not obtain gpio for ENC28J60_IRQ\n");
return;
}
spi_register_board_info(omap3beagle_zippy_spi_board_info,
ARRAY_SIZE(omap3beagle_zippy_spi_board_info));
}
#else
static inline void __init omap3beagle_enc28j60_init(void) { return; }
7.8 Modified code for board-omap3beagle.c
61
#endif
#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
#include <plat/mcspi.h>
#include <linux/spi/spi.h>
#define OMAP3BEAGLE_GPIO_KS8851_IRQ 157
static struct omap2_mcspi_device_config ks8851_spi_chip_info = {
.turbo_mode = 0,
.single_channel = 1,/* 0: slave, 1: master */
};
static struct spi_board_info
omap3beagle_zippy2_spi_board_info[] __initdata = {
{
.modalias = "ks8851",
.bus_num = 4,
.chip_select = 0,
.max_speed_hz = 36000000,
.controller_data = &ks8851_spi_chip_info,
},
};
static void __init omap3beagle_ks8851_init(void)
{
if ((gpio_request(OMAP3BEAGLE_GPIO_KS8851_IRQ, "KS8851_IRQ") == 0) &&
(gpio_direction_input(OMAP3BEAGLE_GPIO_KS8851_IRQ) == 0)) {
gpio_export(OMAP3BEAGLE_GPIO_KS8851_IRQ, 0);
omap3beagle_zippy2_spi_board_info[0].irq =
OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_KS8851_IRQ);
set_irq_type(omap3beagle_zippy2_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
} else {
printk(KERN_ERR "could not obtain gpio for KS8851_IRQ\n");
return;
}
spi_register_board_info(omap3beagle_zippy2_spi_board_info,
ARRAY_SIZE(omap3beagle_zippy2_spi_board_info));
}
#else
static inline void __init omap3beagle_ks8851_init(void) { return; }
#endif
62
Appendices
static struct mtd_partition omap3beagle_nand_partitions[] = {
/* All the partition sizes are listed in terms of NAND block size */
{
.name = "X-Loader",
.offset = 0,
.size = 4 * NAND_BLOCK_SIZE,
.mask_flags = MTD_WRITEABLE,/* force read-only */
},
{
.name = "U-Boot",
.offset = MTDPART_OFS_APPEND,/* Offset = 0x80000 */
.size = 15 * NAND_BLOCK_SIZE,
},
{
.name = "U-Boot Env",
.offset = MTDPART_OFS_APPEND,/* Offset = 0x260000 */
.size = 1 * NAND_BLOCK_SIZE,
},
{
.name = "Kernel",
.offset = MTDPART_OFS_APPEND,/* Offset = 0x280000 */
.size = 32 * NAND_BLOCK_SIZE,
},
{
.name = "File System",
.offset = MTDPART_OFS_APPEND,/* Offset = 0x680000 */
.size = MTDPART_SIZ_FULL,
},
};
static struct omap_nand_platform_data omap3beagle_nand_data = {
.options = NAND_BUSWIDTH_16,
.parts = omap3beagle_nand_partitions,
.nr_parts = ARRAY_SIZE(omap3beagle_nand_partitions),
.dma_channel = -1,/* disable DMA in OMAP NAND driver */
.nand_setup = NULL,
.dev_ready = NULL,
};
static struct resource omap3beagle_nand_resource = {
.flags = IORESOURCE_MEM,
};
static struct platform_device omap3beagle_nand_device = {
.name = "omap2-nand",
.id = -1,
7.8 Modified code for board-omap3beagle.c
.dev = {
.platform_data = &omap3beagle_nand_data,
},
.num_resources = 1,
.resource = &omap3beagle_nand_resource,
};
/* DSS */
static int beagle_enable_dvi(struct omap_dss_device *dssdev)
{
if (dssdev->reset_gpio != -1)
gpio_set_value(dssdev->reset_gpio, 1);
return 0;
}
static void beagle_disable_dvi(struct omap_dss_device *dssdev)
{
if (dssdev->reset_gpio != -1)
gpio_set_value(dssdev->reset_gpio, 0);
}
static struct omap_dss_device beagle_dvi_device = {
.type = OMAP_DISPLAY_TYPE_DPI,
.name = "dvi",
.driver_name = "generic_panel",
.phy.dpi.data_lines = 24,
.reset_gpio = 170,
.platform_enable = beagle_enable_dvi,
.platform_disable = beagle_disable_dvi,
};
static int beagle_panel_enable_tv(struct omap_dss_device *dssdev)
{
#define ENABLE_VDAC_DEDICATED
0x03
#define ENABLE_VDAC_DEV_GRP
0x20
twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
ENABLE_VDAC_DEDICATED,
TWL4030_VDAC_DEDICATED);
twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
return 0;
}
63
64
Appendices
static void beagle_panel_disable_tv(struct omap_dss_device *dssdev)
{
twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
TWL4030_VDAC_DEDICATED);
twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
TWL4030_VDAC_DEV_GRP);
}
static struct omap_dss_device beagle_tv_device = {
.name = "tv",
.driver_name = "venc",
.type = OMAP_DISPLAY_TYPE_VENC,
.phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
.platform_enable = beagle_panel_enable_tv,
.platform_disable = beagle_panel_disable_tv,
};
static struct omap_dss_device *beagle_dss_devices[] = {
&beagle_dvi_device,
&beagle_tv_device,
};
static struct omap_dss_board_info beagle_dss_data = {
.num_devices = ARRAY_SIZE(beagle_dss_devices),
.devices = beagle_dss_devices,
.default_device = &beagle_dvi_device,
};
static struct platform_device beagle_dss_device = {
.name
= "omapdss",
.id
= -1,
.dev
= {
.platform_data = &beagle_dss_data,
},
};
static struct regulator_consumer_supply beagle_vdac_supply = {
.supply = "vdda_dac",
.dev = &beagle_dss_device.dev,
};
static struct regulator_consumer_supply beagle_vdvi_supply = {
.supply = "vdds_dsi",
.dev = &beagle_dss_device.dev,
};
7.8 Modified code for board-omap3beagle.c
static void __init beagle_display_init(void)
{
int r;
r = gpio_request(beagle_dvi_device.reset_gpio, "DVI reset");
if (r < 0) {
printk(KERN_ERR "Unable to get DVI reset GPIO\n");
return;
}
gpio_direction_output(beagle_dvi_device.reset_gpio, 0);
}
#include "sdram-micron-mt46h32m32lf-6.h"
static struct twl4030_hsmmc_info mmc[] = {
{
.mmc = 1,
.wires = 8,
.gpio_wp = -1,
},
{
.mmc = 2,
.wires = 4,
.transceiver = true,
.ocr_mask = 0x00100000,/* 3.3V */
},
{} /* Terminator */
};
static struct regulator_consumer_supply beagle_vmmc1_supply = {
.supply = "vmmc",
};
static struct regulator_consumer_supply beagle_vsim_supply = {
.supply = "vmmc_aux",
};
static struct gpio_led gpio_leds[];
static int beagle_twl_gpio_setup(struct device *dev,
unsigned gpio, unsigned ngpio)
{
if (system_rev >= 0x20 && system_rev <= 0x34301000) {
if (cpu_is_omap3630()) {
65
66
Appendices
mmc[0].gpio_wp = -1;
}
else {
mmc[0].gpio_wp = 23;
omap_mux_init_gpio(23, OMAP_PIN_INPUT);
}
} else {
mmc[0].gpio_wp = 29;
omap_mux_init_gpio(29, OMAP_PIN_INPUT);
}
/* gpio + 0 is "mmc0_cd" (input/IRQ) */
mmc[0].gpio_cd = gpio + 0;
twl4030_mmc_init(mmc);
/* link regulators to MMC adapters */
beagle_vmmc1_supply.dev = mmc[0].dev;
beagle_vsim_supply.dev = mmc[0].dev;
/* REVISIT: need ehci-omap hooks for external VBUS
* power switch and overcurrent detect
*/
if (cpu_is_omap3630()) {
/* Power on DVI, Serial and PWR led */
gpio_request(gpio + 1, "nDVI_PWR_EN");
gpio_direction_output(gpio + 1, 0);
/* Power on camera interface */
gpio_request(gpio + 2, "CAM_EN");
gpio_direction_output(gpio + 2, 1);
/* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
}
else {
gpio_request(gpio + 1, "EHCI_nOC");
gpio_direction_input(gpio + 1);
/* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
}
/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
7.8 Modified code for board-omap3beagle.c
gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
return 0;
}
static struct twl4030_gpio_platform_data beagle_gpio_data = {
.gpio_base = OMAP_MAX_GPIO_LINES,
.irq_base = TWL4030_GPIO_IRQ_BASE,
.irq_end = TWL4030_GPIO_IRQ_END,
.use_leds = true,
.pullups = BIT(1),
.pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
| BIT(15) | BIT(16) | BIT(17),
.setup = beagle_twl_gpio_setup,
};
static struct platform_device beagle_cam_device = {
.name = "beagle_cam",
.id = -1,
};
static struct regulator_consumer_supply beagle_vaux3_supply = {
.supply = "cam_1v8",
.dev = &beagle_cam_device.dev,
};
static struct regulator_consumer_supply beagle_vaux4_supply = {
.supply = "cam_2v8",
.dev = &beagle_cam_device.dev,
};
/* VAUX3 for CAM_1V8 */
static struct regulator_init_data beagle_vaux3 = {
.constraints = {
.min_uV = 1800000,
.max_uV = 1800000,
.apply_uV = true,
.valid_modes_mask = REGULATOR_MODE_NORMAL
| REGULATOR_MODE_STANDBY,
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
.consumer_supplies = &beagle_vaux3_supply,
};
67
68
Appendices
/* VAUX4 for CAM_2V8 */
static struct regulator_init_data beagle_vaux4 = {
.constraints = {
.min_uV = 1800000,
.max_uV = 1800000,
.apply_uV = true,
.valid_modes_mask = REGULATOR_MODE_NORMAL
| REGULATOR_MODE_STANDBY,
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
.consumer_supplies = &beagle_vaux4_supply,
};
/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3
(20 mA, plus card == max 220 mA) */
static struct regulator_init_data beagle_vmmc1 = {
.constraints = {
.min_uV = 1850000,
.max_uV = 3150000,
.valid_modes_mask = REGULATOR_MODE_NORMAL
| REGULATOR_MODE_STANDBY,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
.consumer_supplies = &beagle_vmmc1_supply,
};
/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
static struct regulator_init_data beagle_vsim = {
.constraints = {
.min_uV = 1800000,
.max_uV = 3000000,
.valid_modes_mask = REGULATOR_MODE_NORMAL
| REGULATOR_MODE_STANDBY,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
| REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
.consumer_supplies = &beagle_vsim_supply,
};
7.8 Modified code for board-omap3beagle.c
/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
static struct regulator_init_data beagle_vdac = {
.constraints = {
.min_uV = 1800000,
.max_uV = 1800000,
.valid_modes_mask = REGULATOR_MODE_NORMAL
| REGULATOR_MODE_STANDBY,
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
.consumer_supplies = &beagle_vdac_supply,
};
/* VPLL2 for digital video outputs */
static struct regulator_init_data beagle_vpll2 = {
.constraints = {
.name = "VDVI",
.min_uV = 1800000,
.max_uV = 1800000,
.valid_modes_mask = REGULATOR_MODE_NORMAL
| REGULATOR_MODE_STANDBY,
.valid_ops_mask = REGULATOR_CHANGE_MODE
| REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
.consumer_supplies = &beagle_vdvi_supply,
};
static struct twl4030_usb_data beagle_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
static struct twl4030_codec_audio_data beagle_audio_data = {
.audio_mclk = 26000000,
};
static struct twl4030_codec_data beagle_codec_data = {
.audio_mclk = 26000000,
.audio = &beagle_audio_data,
};
static struct twl4030_madc_platform_data beagle_madc_data = {
.irq_line = 1,
};
69
70
Appendices
static struct twl4030_platform_data beagle_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.usb = &beagle_usb_data,
.gpio = &beagle_gpio_data,
/*.codec = &beagle_codec_data, */
.madc = &beagle_madc_data,
.vmmc1 = &beagle_vmmc1,
.vsim = &beagle_vsim,
.vdac = &beagle_vdac,
.vpll2 = &beagle_vpll2,
.vaux3 = &beagle_vaux3,
.vaux4 = &beagle_vaux4,
};
static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = {
{
I2C_BOARD_INFO("tlv320aic3x", 0x18),
},
{
I2C_BOARD_INFO("twl4030", 0x48),
.flags = I2C_CLIENT_WAKE,
.irq = INT_34XX_SYS_NIRQ,
.platform_data = &beagle_twldata,
},
};
#if defined(CONFIG_EEPROM_AT24) || defined(CONFIG_EEPROM_AT24_MODULE)
#include <linux/i2c/at24.h>
static struct at24_platform_data m24c01 = {
.byte_len
= SZ_1K / 8,
.page_size
= 16,
};
#if defined(CONFIG_RTC_DRV_DS1307) || \
defined(CONFIG_RTC_DRV_DS1307_MODULE)
static struct i2c_board_info __initdata beagle_zippy_i2c2_boardinfo[] = {
{
I2C_BOARD_INFO("ds1307", 0x68),
},
7.8 Modified code for board-omap3beagle.c
71
{
I2C_BOARD_INFO("24c01", 0x50),
.platform_data = &m24c01,
},
};
#else
static struct i2c_board_info __initdata beagle_zippy_i2c2_boardinfo[] = {
{
I2C_BOARD_INFO("24c01", 0x50),
.platform_data = &m24c01,
},
};
#endif
#else
static struct i2c_board_info __initdata beagle_zippy_i2c2_boardinfo[] = {};
#endif
static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {
#if defined(CONFIG_VIDEO_MT9V113) || defined(CONFIG_VIDEO_MT9V113_MODULE)
{
I2C_BOARD_INFO("mt9v113", MT9V113_I2C_ADDR),
.platform_data = &mt9v113_pdata,
},
#endif
#if defined(CONFIG_VIDEO_MT9T112) || defined(CONFIG_VIDEO_MT9T112_MODULE)
{
I2C_BOARD_INFO("mt9t112", MT9T112_I2C_ADDR),
.platform_data = &mt9t112_pdata,
},
#endif
};
static int __init omap3_beagle_i2c_init(void)
{
omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo,
ARRAY_SIZE(beagle_i2c1_boardinfo));
if(!strcmp(expansionboard_name, "zippy") ||
!strcmp(expansionboard_name, "zippy2"))
{
printk(KERN_INFO "Beagle expansionboard:
registering i2c2 bus for zippy/zippy2\n");
omap_register_i2c_bus(2, 400, beagle_zippy_i2c2_boardinfo,
ARRAY_SIZE(beagle_zippy_i2c2_boardinfo));
} else if (cpu_is_omap3630()) {
omap_register_i2c_bus(2, 400, beagle_i2c2_boardinfo,
ARRAY_SIZE(beagle_i2c2_boardinfo));
72
Appendices
} else {
omap_register_i2c_bus(2, 100, NULL, 0);
}
/* Bus 3 is attached to the DVI port where devices like the pico DLP
* projector don’t work reliably with 400kHz */
omap_register_i2c_bus(3, 100, NULL, 0);
return 0;
}
static struct gpio_led gpio_leds[] = {
{
.name = "beagleboard::usr0",
.default_trigger = "heartbeat",
.gpio = 150,
},
{
.name = "beagleboard::usr1",
.default_trigger = "mmc0",
.gpio = 149,
},
{
.name = "beagleboard::pmu_stat",
.gpio = -EINVAL,/* gets replaced */
.active_low = true,
},
};
static struct gpio_led_platform_data gpio_led_info = {
.leds = gpio_leds,
.num_leds = ARRAY_SIZE(gpio_leds),
};
static struct platform_device leds_gpio = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = &gpio_led_info,
},
};
static struct gpio_keys_button gpio_buttons[] = {
{
.code = BTN_EXTRA,
.gpio = 7,
.desc = "user",
.wakeup = 1,
7.8 Modified code for board-omap3beagle.c
73
},
};
static struct gpio_keys_platform_data gpio_key_info = {
.buttons = gpio_buttons,
.nbuttons = ARRAY_SIZE(gpio_buttons),
};
static struct platform_device keys_gpio = {
.name = "gpio-keys",
.id = -1,
.dev = {
.platform_data = &gpio_key_info,
},
};
static void __init omap3_beagle_init_irq(void)
{
if (cpu_is_omap3630())
{
omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
NULL,
_omap37x_mpu_rate_table,
_omap37x_dsp_rate_table,
_omap37x_l3_rate_table);
}
else
{
omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
NULL,
_omap35x_mpu_rate_table,
_omap35x_dsp_rate_table,
_omap35x_l3_rate_table);
}
omap_init_irq();
#ifdef CONFIG_OMAP_32K_TIMER
omap2_gp_clockevent_set_gptimer(12);
#endif
omap_gpio_init();
}
static struct platform_device *omap3_beagle_devices[] __initdata = {
&leds_gpio,
&keys_gpio,
&beagle_dss_device,
&beagle_cam_device,
74
Appendices
};
static void __init omap3beagle_flash_init(void)
{
u8 cs = 0;
u8 nandcs = GPMC_CS_NUM + 1;
u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
/* find out the chip-select on which NAND exists */
while (cs < GPMC_CS_NUM) {
u32 ret = 0;
ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
if ((ret & 0xC00) == 0x800) {
printk(KERN_INFO "Found NAND on CS%d\n", cs);
if (nandcs > GPMC_CS_NUM)
nandcs = cs;
}
cs++;
}
if (nandcs > GPMC_CS_NUM) {
printk(KERN_INFO "NAND: Unable to find configuration "
"in GPMC\n ");
return;
}
if (nandcs < GPMC_CS_NUM) {
omap3beagle_nand_data.cs = nandcs;
omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
(gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
if (platform_device_register(&omap3beagle_nand_device) < 0)
printk(KERN_ERR "Unable to register NAND device\n");
}
}
static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = {
.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
7.8 Modified code for board-omap3beagle.c
.phy_reset = true,
.reset_gpio_port[0]
.reset_gpio_port[1]
.reset_gpio_port[2]
};
75
= -EINVAL,
= 147,
= -EINVAL
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
/* McBSPi Mappings, Clocks CLKX and FSX are outputs */
OMAP3_MUX(UART2_CTS, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
OMAP3_MUX(UART2_TX, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
OMAP3_MUX(MCBSP3_FSX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(UART2_RTS, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
OMAP3_MUX(MCBSP1_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(MCBSP1_FSX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
OMAP3_MUX(MCBSP1_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
OMAP3_MUX(SDMMC2_DAT6, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
/*I2C Mappings*/
OMAP3_MUX(I2C2_SDA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
OMAP3_MUX(I2C2_SCL, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
#else
#define board_mux NULL
#endif
static int __init expansionboard_setup(char *str)
{
if (!str)
return -EINVAL;
strncpy(expansionboard_name, str, 16);
printk(KERN_INFO "Beagle expansionboard: %s\n", expansionboard_name);
return 0;
}
static void __init omap3_beagle_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
omap3_beagle_i2c_init();
platform_add_devices(omap3_beagle_devices,
ARRAY_SIZE(omap3_beagle_devices));
omap_serial_init();
omap_mux_init_gpio(170, OMAP_PIN_INPUT);
gpio_request(170, "DVI_nPD");
76
Appendices
/* REVISIT leave DVI powered down until it’s needed ... */
gpio_direction_output(170, true);
if(!strcmp(expansionboard_name, "zippy"))
{
printk(KERN_INFO "Beagle expansionboard: initializing enc28j60\n");
omap3beagle_enc28j60_init();
printk(KERN_INFO "Beagle expansionboard:
assigning GPIO 141 and 162 to MMC1\n");
mmc[1].gpio_wp = 141;
mmc[1].gpio_cd = 162;
}
if(!strcmp(expansionboard_name, "zippy2"))
{
printk(KERN_INFO "Beagle expansionboard: initializing ks_8851\n");
omap3beagle_ks8851_init();
printk(KERN_INFO "Beagle expansionboard:
assigning GPIO 141 and 162 to MMC1\n");
mmc[1].gpio_wp = 141;
mmc[1].gpio_cd = 162;
}
if(!strcmp(expansionboard_name, "trainer"))
{
printk(KERN_INFO "Beagle expansionboard:
exporting GPIOs 130-141,162 to userspace\n");
gpio_request(130, "sysfs");
gpio_export(130, 1);
gpio_request(131, "sysfs");
gpio_export(131, 1);
gpio_request(132, "sysfs");
gpio_export(132, 1);
gpio_request(133, "sysfs");
gpio_export(133, 1);
gpio_request(134, "sysfs");
gpio_export(134, 1);
gpio_request(135, "sysfs");
gpio_export(135, 1);
gpio_request(136, "sysfs");
gpio_export(136, 1);
gpio_request(137, "sysfs");
gpio_export(137, 1);
gpio_request(138, "sysfs");
gpio_export(138, 1);
gpio_request(139, "sysfs");
7.8 Modified code for board-omap3beagle.c
gpio_export(139, 1);
gpio_request(140, "sysfs");
gpio_export(140, 1);
gpio_request(141, "sysfs");
gpio_export(141, 1);
gpio_request(162, "sysfs");
gpio_export(162, 1);
}
usb_musb_init();
usb_ehci_init(&ehci_pdata);
omap3beagle_flash_init();
/* Ensure SDRC pins are mux’d for self-refresh */
omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
beagle_display_init();
#ifdef CONFIG_USB_ANDROID
omap3evm_android_gadget_init();
#endif
}
static void __init omap3_beagle_map_io(void)
{
omap2_set_globals_343x();
omap2_map_common_io();
}
early_param("buddy", expansionboard_setup);
MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
.phys_io = 0x48000000,
.io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_beagle_map_io,
.init_irq = omap3_beagle_init_irq,
.init_machine = omap3_beagle_init,
.timer = &omap_timer,
MACHINE_END
77
Bibliography
[1] Saab AB. 16136-048-05 Kravmatris SKE.xls. Saab AB, 2011.
[2] Saab AB. Kravspecifikation för RPCS. Saab AB, 2011.
[3] ALSA-Project.
Alsa system-on-chip.
Website, 2010.
alsa-project.org/main/index.php/ASoC.
http://www.
[4] Beagleboard.org. Beagleboard system reference manual rev c4. Website, 2009.
http://beagleboard.org/static/BBSRM_latest.pdf.
[5] Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman. Linux Device Drivers. O’Reilly Media, third edition, 2005. ISBN 0-201-52983-1.
[6] GStreamer. Gstreamer homepage. Website, 2011. http://www.gstreamer.
net.
[7] Texas Instruments. Low power stereo audio codec for portable audio/telephony (rev. c) datasheet. Website, 2008. http://www.ti.com/lit/ds/
symlink/tlv320aic31.pdf.
[8] Texas Instruments. Omap35x applications processor technical reference manual. Website, 2011. http://www.ti.com/lit/ug/spruf98u/spruf98u.pdf.
[9] Texas Instruments. Ti android gingerbread 2.3 devkit 1.0 developers
guide.
Website, 2011.
http://processors.wiki.ti.com/index.php/
TI-Android-GingerBread-2.3-DevKit-1.0_DeveloperGuide.
[10] Rowboat. Rowboat - android for texas instruments devices (sitara). Website,
2010. https://code.google.com/p/rowboat/.
79
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Related manuals

Download PDF

advertisement