mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Merge branch 'topic/asoc' into for-linus
* topic/asoc: (226 commits) ASoC: au1x: PSC-AC97 bugfixes ASoC: Fix WM835x Out4 capture enumeration ASoC: Remove unuused hw_read_t ASoC: fix pxa2xx-ac97.c breakage ASoC: Fully specify DC servo bits to update in wm_hubs ASoC: Debugged improper setting of PLL fields in WM8580 driver ASoC: new board driver to connect bfin-5xx with ad1836 codec ASoC: OMAP: Add functionality to set CLKR and FSR sources in McBSP DAI ASoC: davinci: i2c device creation moved into board files ASoC: Don't reconfigure WM8350 FLL if not needed ASoC: Fix s3c-i2s-v2 build ASoC: Make platform data optional for TLV320AIC3x ASoC: Add S3C24xx dependencies for Simtec machines ASoC: SDP3430: Fix TWL GPIO6 pin mux request ASoC: S3C platform: Fix s3c2410_dma_started() called at improper time ARM: OMAP: McBSP: Merge two functions into omap_mcbsp_start/_stop ASoC: OMAP: Fix setup of XCCR and RCCR registers in McBSP DAI OMAP: McBSP: Use textual values in DMA operating mode sysfs files ARM: OMAP: DMA: Add support for DMA channel self linking on OMAP1510 ASoC: Select core DMA when building for S3C64xx ...
This commit is contained in:
commit
e0b3032bcd
138 changed files with 23466 additions and 2791 deletions
|
|
@ -128,6 +128,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
|
|||
.rx_irq = INT_24XX_MCBSP1_IRQ_RX,
|
||||
.tx_irq = INT_24XX_MCBSP1_IRQ_TX,
|
||||
.ops = &omap2_mcbsp_ops,
|
||||
.buffer_size = 0x6F,
|
||||
},
|
||||
{
|
||||
.phys_base = OMAP34XX_MCBSP2_BASE,
|
||||
|
|
@ -136,6 +137,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
|
|||
.rx_irq = INT_24XX_MCBSP2_IRQ_RX,
|
||||
.tx_irq = INT_24XX_MCBSP2_IRQ_TX,
|
||||
.ops = &omap2_mcbsp_ops,
|
||||
.buffer_size = 0x3FF,
|
||||
},
|
||||
{
|
||||
.phys_base = OMAP34XX_MCBSP3_BASE,
|
||||
|
|
@ -144,6 +146,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
|
|||
.rx_irq = INT_24XX_MCBSP3_IRQ_RX,
|
||||
.tx_irq = INT_24XX_MCBSP3_IRQ_TX,
|
||||
.ops = &omap2_mcbsp_ops,
|
||||
.buffer_size = 0x6F,
|
||||
},
|
||||
{
|
||||
.phys_base = OMAP34XX_MCBSP4_BASE,
|
||||
|
|
@ -152,6 +155,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
|
|||
.rx_irq = INT_24XX_MCBSP4_IRQ_RX,
|
||||
.tx_irq = INT_24XX_MCBSP4_IRQ_TX,
|
||||
.ops = &omap2_mcbsp_ops,
|
||||
.buffer_size = 0x6F,
|
||||
},
|
||||
{
|
||||
.phys_base = OMAP34XX_MCBSP5_BASE,
|
||||
|
|
@ -160,6 +164,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
|
|||
.rx_irq = INT_24XX_MCBSP5_IRQ_RX,
|
||||
.tx_irq = INT_24XX_MCBSP5_IRQ_TX,
|
||||
.ops = &omap2_mcbsp_ops,
|
||||
.buffer_size = 0x6F,
|
||||
},
|
||||
};
|
||||
#define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@
|
|||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
|
||||
/*
|
||||
* @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95)
|
||||
* a -1 value means no gpio will be used for reset
|
||||
* @codec_pdata: AC97 codec platform_data
|
||||
|
||||
* reset_gpio should only be specified for pxa27x CPUs where a silicon
|
||||
* bug prevents correct operation of the reset line. If not specified,
|
||||
|
|
@ -20,6 +22,7 @@ typedef struct {
|
|||
void (*resume)(void *);
|
||||
void *priv;
|
||||
int reset_gpio;
|
||||
void *codec_pdata[AC97_BUS_MAX_DEVICES];
|
||||
} pxa2xx_audio_ops_t;
|
||||
|
||||
extern void pxa_set_ac97_info(pxa2xx_audio_ops_t *ops);
|
||||
|
|
|
|||
|
|
@ -1127,6 +1127,11 @@ int omap_dma_running(void)
|
|||
void omap_dma_link_lch(int lch_head, int lch_queue)
|
||||
{
|
||||
if (omap_dma_in_1510_mode()) {
|
||||
if (lch_head == lch_queue) {
|
||||
dma_write(dma_read(CCR(lch_head)) | (3 << 8),
|
||||
CCR(lch_head));
|
||||
return;
|
||||
}
|
||||
printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
|
||||
BUG();
|
||||
return;
|
||||
|
|
@ -1149,6 +1154,11 @@ EXPORT_SYMBOL(omap_dma_link_lch);
|
|||
void omap_dma_unlink_lch(int lch_head, int lch_queue)
|
||||
{
|
||||
if (omap_dma_in_1510_mode()) {
|
||||
if (lch_head == lch_queue) {
|
||||
dma_write(dma_read(CCR(lch_head)) & ~(3 << 8),
|
||||
CCR(lch_head));
|
||||
return;
|
||||
}
|
||||
printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
|
||||
BUG();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -134,6 +134,11 @@
|
|||
#define OMAP_MCBSP_REG_XCERG 0x74
|
||||
#define OMAP_MCBSP_REG_XCERH 0x78
|
||||
#define OMAP_MCBSP_REG_SYSCON 0x8C
|
||||
#define OMAP_MCBSP_REG_THRSH2 0x90
|
||||
#define OMAP_MCBSP_REG_THRSH1 0x94
|
||||
#define OMAP_MCBSP_REG_IRQST 0xA0
|
||||
#define OMAP_MCBSP_REG_IRQEN 0xA4
|
||||
#define OMAP_MCBSP_REG_WAKEUPEN 0xA8
|
||||
#define OMAP_MCBSP_REG_XCCR 0xAC
|
||||
#define OMAP_MCBSP_REG_RCCR 0xB0
|
||||
|
||||
|
|
@ -249,8 +254,27 @@
|
|||
#define RDISABLE 0x0001
|
||||
|
||||
/********************** McBSP SYSCONFIG bit definitions ********************/
|
||||
#define CLOCKACTIVITY(value) ((value)<<8)
|
||||
#define SIDLEMODE(value) ((value)<<3)
|
||||
#define ENAWAKEUP 0x0004
|
||||
#define SOFTRST 0x0002
|
||||
|
||||
/********************** McBSP DMA operating modes **************************/
|
||||
#define MCBSP_DMA_MODE_ELEMENT 0
|
||||
#define MCBSP_DMA_MODE_THRESHOLD 1
|
||||
#define MCBSP_DMA_MODE_FRAME 2
|
||||
|
||||
/********************** McBSP WAKEUPEN bit definitions *********************/
|
||||
#define XEMPTYEOFEN 0x4000
|
||||
#define XRDYEN 0x0400
|
||||
#define XEOFEN 0x0200
|
||||
#define XFSXEN 0x0100
|
||||
#define XSYNCERREN 0x0080
|
||||
#define RRDYEN 0x0008
|
||||
#define REOFEN 0x0004
|
||||
#define RFSREN 0x0002
|
||||
#define RSYNCERREN 0x0001
|
||||
|
||||
/* we don't do multichannel for now */
|
||||
struct omap_mcbsp_reg_cfg {
|
||||
u16 spcr2;
|
||||
|
|
@ -344,6 +368,9 @@ struct omap_mcbsp_platform_data {
|
|||
u8 dma_rx_sync, dma_tx_sync;
|
||||
u16 rx_irq, tx_irq;
|
||||
struct omap_mcbsp_ops *ops;
|
||||
#ifdef CONFIG_ARCH_OMAP34XX
|
||||
u16 buffer_size;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct omap_mcbsp {
|
||||
|
|
@ -377,6 +404,11 @@ struct omap_mcbsp {
|
|||
struct omap_mcbsp_platform_data *pdata;
|
||||
struct clk *iclk;
|
||||
struct clk *fclk;
|
||||
#ifdef CONFIG_ARCH_OMAP34XX
|
||||
int dma_op_mode;
|
||||
u16 max_tx_thres;
|
||||
u16 max_rx_thres;
|
||||
#endif
|
||||
};
|
||||
extern struct omap_mcbsp **mcbsp_ptr;
|
||||
extern int omap_mcbsp_count;
|
||||
|
|
@ -385,10 +417,25 @@ int omap_mcbsp_init(void);
|
|||
void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
|
||||
int size);
|
||||
void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
|
||||
#ifdef CONFIG_ARCH_OMAP34XX
|
||||
void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
|
||||
void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
|
||||
u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
|
||||
u16 omap_mcbsp_get_max_rx_threshold(unsigned int id);
|
||||
int omap_mcbsp_get_dma_op_mode(unsigned int id);
|
||||
#else
|
||||
static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
|
||||
{ }
|
||||
static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
|
||||
{ }
|
||||
static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; }
|
||||
static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; }
|
||||
static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; }
|
||||
#endif
|
||||
int omap_mcbsp_request(unsigned int id);
|
||||
void omap_mcbsp_free(unsigned int id);
|
||||
void omap_mcbsp_start(unsigned int id);
|
||||
void omap_mcbsp_stop(unsigned int id);
|
||||
void omap_mcbsp_start(unsigned int id, int tx, int rx);
|
||||
void omap_mcbsp_stop(unsigned int id, int tx, int rx);
|
||||
void omap_mcbsp_xmit_word(unsigned int id, u32 word);
|
||||
u32 omap_mcbsp_recv_word(unsigned int id);
|
||||
|
||||
|
|
|
|||
|
|
@ -198,6 +198,170 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
|
|||
}
|
||||
EXPORT_SYMBOL(omap_mcbsp_config);
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP34XX
|
||||
/*
|
||||
* omap_mcbsp_set_tx_threshold configures how to deal
|
||||
* with transmit threshold. the threshold value and handler can be
|
||||
* configure in here.
|
||||
*/
|
||||
void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
|
||||
{
|
||||
struct omap_mcbsp *mcbsp;
|
||||
void __iomem *io_base;
|
||||
|
||||
if (!cpu_is_omap34xx())
|
||||
return;
|
||||
|
||||
if (!omap_mcbsp_check_valid_id(id)) {
|
||||
printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
|
||||
return;
|
||||
}
|
||||
mcbsp = id_to_mcbsp_ptr(id);
|
||||
io_base = mcbsp->io_base;
|
||||
|
||||
OMAP_MCBSP_WRITE(io_base, THRSH2, threshold);
|
||||
}
|
||||
EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold);
|
||||
|
||||
/*
|
||||
* omap_mcbsp_set_rx_threshold configures how to deal
|
||||
* with receive threshold. the threshold value and handler can be
|
||||
* configure in here.
|
||||
*/
|
||||
void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
|
||||
{
|
||||
struct omap_mcbsp *mcbsp;
|
||||
void __iomem *io_base;
|
||||
|
||||
if (!cpu_is_omap34xx())
|
||||
return;
|
||||
|
||||
if (!omap_mcbsp_check_valid_id(id)) {
|
||||
printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
|
||||
return;
|
||||
}
|
||||
mcbsp = id_to_mcbsp_ptr(id);
|
||||
io_base = mcbsp->io_base;
|
||||
|
||||
OMAP_MCBSP_WRITE(io_base, THRSH1, threshold);
|
||||
}
|
||||
EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold);
|
||||
|
||||
/*
|
||||
* omap_mcbsp_get_max_tx_thres just return the current configured
|
||||
* maximum threshold for transmission
|
||||
*/
|
||||
u16 omap_mcbsp_get_max_tx_threshold(unsigned int id)
|
||||
{
|
||||
struct omap_mcbsp *mcbsp;
|
||||
|
||||
if (!omap_mcbsp_check_valid_id(id)) {
|
||||
printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
|
||||
return -ENODEV;
|
||||
}
|
||||
mcbsp = id_to_mcbsp_ptr(id);
|
||||
|
||||
return mcbsp->max_tx_thres;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_mcbsp_get_max_tx_threshold);
|
||||
|
||||
/*
|
||||
* omap_mcbsp_get_max_rx_thres just return the current configured
|
||||
* maximum threshold for reception
|
||||
*/
|
||||
u16 omap_mcbsp_get_max_rx_threshold(unsigned int id)
|
||||
{
|
||||
struct omap_mcbsp *mcbsp;
|
||||
|
||||
if (!omap_mcbsp_check_valid_id(id)) {
|
||||
printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
|
||||
return -ENODEV;
|
||||
}
|
||||
mcbsp = id_to_mcbsp_ptr(id);
|
||||
|
||||
return mcbsp->max_rx_thres;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold);
|
||||
|
||||
/*
|
||||
* omap_mcbsp_get_dma_op_mode just return the current configured
|
||||
* operating mode for the mcbsp channel
|
||||
*/
|
||||
int omap_mcbsp_get_dma_op_mode(unsigned int id)
|
||||
{
|
||||
struct omap_mcbsp *mcbsp;
|
||||
int dma_op_mode;
|
||||
|
||||
if (!omap_mcbsp_check_valid_id(id)) {
|
||||
printk(KERN_ERR "%s: Invalid id (%u)\n", __func__, id + 1);
|
||||
return -ENODEV;
|
||||
}
|
||||
mcbsp = id_to_mcbsp_ptr(id);
|
||||
|
||||
spin_lock_irq(&mcbsp->lock);
|
||||
dma_op_mode = mcbsp->dma_op_mode;
|
||||
spin_unlock_irq(&mcbsp->lock);
|
||||
|
||||
return dma_op_mode;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode);
|
||||
|
||||
static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp)
|
||||
{
|
||||
/*
|
||||
* Enable wakup behavior, smart idle and all wakeups
|
||||
* REVISIT: some wakeups may be unnecessary
|
||||
*/
|
||||
if (cpu_is_omap34xx()) {
|
||||
u16 syscon;
|
||||
|
||||
syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON);
|
||||
syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03));
|
||||
|
||||
spin_lock_irq(&mcbsp->lock);
|
||||
if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
|
||||
syscon |= (ENAWAKEUP | SIDLEMODE(0x02) |
|
||||
CLOCKACTIVITY(0x02));
|
||||
OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN,
|
||||
XRDYEN | RRDYEN);
|
||||
} else {
|
||||
syscon |= SIDLEMODE(0x01);
|
||||
}
|
||||
spin_unlock_irq(&mcbsp->lock);
|
||||
|
||||
OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp)
|
||||
{
|
||||
/*
|
||||
* Disable wakup behavior, smart idle and all wakeups
|
||||
*/
|
||||
if (cpu_is_omap34xx()) {
|
||||
u16 syscon;
|
||||
|
||||
syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON);
|
||||
syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03));
|
||||
/*
|
||||
* HW bug workaround - If no_idle mode is taken, we need to
|
||||
* go to smart_idle before going to always_idle, or the
|
||||
* device will not hit retention anymore.
|
||||
*/
|
||||
syscon |= SIDLEMODE(0x02);
|
||||
OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
|
||||
|
||||
syscon &= ~(SIDLEMODE(0x03));
|
||||
OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
|
||||
|
||||
OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, 0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {}
|
||||
static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We can choose between IRQ based or polled IO.
|
||||
* This needs to be called before omap_mcbsp_request().
|
||||
|
|
@ -257,6 +421,9 @@ int omap_mcbsp_request(unsigned int id)
|
|||
clk_enable(mcbsp->iclk);
|
||||
clk_enable(mcbsp->fclk);
|
||||
|
||||
/* Do procedure specific to omap34xx arch, if applicable */
|
||||
omap34xx_mcbsp_request(mcbsp);
|
||||
|
||||
/*
|
||||
* Make sure that transmitter, receiver and sample-rate generator are
|
||||
* not running before activating IRQs.
|
||||
|
|
@ -305,6 +472,9 @@ void omap_mcbsp_free(unsigned int id)
|
|||
if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
|
||||
mcbsp->pdata->ops->free(id);
|
||||
|
||||
/* Do procedure specific to omap34xx arch, if applicable */
|
||||
omap34xx_mcbsp_free(mcbsp);
|
||||
|
||||
clk_disable(mcbsp->fclk);
|
||||
clk_disable(mcbsp->iclk);
|
||||
|
||||
|
|
@ -328,14 +498,15 @@ void omap_mcbsp_free(unsigned int id)
|
|||
EXPORT_SYMBOL(omap_mcbsp_free);
|
||||
|
||||
/*
|
||||
* Here we start the McBSP, by enabling the sample
|
||||
* generator, both transmitter and receivers,
|
||||
* and the frame sync.
|
||||
* Here we start the McBSP, by enabling transmitter, receiver or both.
|
||||
* If no transmitter or receiver is active prior calling, then sample-rate
|
||||
* generator and frame sync are started.
|
||||
*/
|
||||
void omap_mcbsp_start(unsigned int id)
|
||||
void omap_mcbsp_start(unsigned int id, int tx, int rx)
|
||||
{
|
||||
struct omap_mcbsp *mcbsp;
|
||||
void __iomem *io_base;
|
||||
int idle;
|
||||
u16 w;
|
||||
|
||||
if (!omap_mcbsp_check_valid_id(id)) {
|
||||
|
|
@ -348,32 +519,58 @@ void omap_mcbsp_start(unsigned int id)
|
|||
mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7;
|
||||
mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7;
|
||||
|
||||
/* Start the sample generator */
|
||||
w = OMAP_MCBSP_READ(io_base, SPCR2);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
|
||||
idle = !((OMAP_MCBSP_READ(io_base, SPCR2) |
|
||||
OMAP_MCBSP_READ(io_base, SPCR1)) & 1);
|
||||
|
||||
if (idle) {
|
||||
/* Start the sample generator */
|
||||
w = OMAP_MCBSP_READ(io_base, SPCR2);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
|
||||
}
|
||||
|
||||
/* Enable transmitter and receiver */
|
||||
tx &= 1;
|
||||
w = OMAP_MCBSP_READ(io_base, SPCR2);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR2, w | tx);
|
||||
|
||||
rx &= 1;
|
||||
w = OMAP_MCBSP_READ(io_base, SPCR1);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR1, w | rx);
|
||||
|
||||
udelay(100);
|
||||
/*
|
||||
* Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec
|
||||
* REVISIT: 100us may give enough time for two CLKSRG, however
|
||||
* due to some unknown PM related, clock gating etc. reason it
|
||||
* is now at 500us.
|
||||
*/
|
||||
udelay(500);
|
||||
|
||||
/* Start frame sync */
|
||||
w = OMAP_MCBSP_READ(io_base, SPCR2);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
|
||||
if (idle) {
|
||||
/* Start frame sync */
|
||||
w = OMAP_MCBSP_READ(io_base, SPCR2);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
|
||||
}
|
||||
|
||||
if (cpu_is_omap2430() || cpu_is_omap34xx()) {
|
||||
/* Release the transmitter and receiver */
|
||||
w = OMAP_MCBSP_READ(io_base, XCCR);
|
||||
w &= ~(tx ? XDISABLE : 0);
|
||||
OMAP_MCBSP_WRITE(io_base, XCCR, w);
|
||||
w = OMAP_MCBSP_READ(io_base, RCCR);
|
||||
w &= ~(rx ? RDISABLE : 0);
|
||||
OMAP_MCBSP_WRITE(io_base, RCCR, w);
|
||||
}
|
||||
|
||||
/* Dump McBSP Regs */
|
||||
omap_mcbsp_dump_reg(id);
|
||||
}
|
||||
EXPORT_SYMBOL(omap_mcbsp_start);
|
||||
|
||||
void omap_mcbsp_stop(unsigned int id)
|
||||
void omap_mcbsp_stop(unsigned int id, int tx, int rx)
|
||||
{
|
||||
struct omap_mcbsp *mcbsp;
|
||||
void __iomem *io_base;
|
||||
int idle;
|
||||
u16 w;
|
||||
|
||||
if (!omap_mcbsp_check_valid_id(id)) {
|
||||
|
|
@ -385,16 +582,33 @@ void omap_mcbsp_stop(unsigned int id)
|
|||
io_base = mcbsp->io_base;
|
||||
|
||||
/* Reset transmitter */
|
||||
tx &= 1;
|
||||
if (cpu_is_omap2430() || cpu_is_omap34xx()) {
|
||||
w = OMAP_MCBSP_READ(io_base, XCCR);
|
||||
w |= (tx ? XDISABLE : 0);
|
||||
OMAP_MCBSP_WRITE(io_base, XCCR, w);
|
||||
}
|
||||
w = OMAP_MCBSP_READ(io_base, SPCR2);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1));
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~tx);
|
||||
|
||||
/* Reset receiver */
|
||||
rx &= 1;
|
||||
if (cpu_is_omap2430() || cpu_is_omap34xx()) {
|
||||
w = OMAP_MCBSP_READ(io_base, RCCR);
|
||||
w |= (tx ? RDISABLE : 0);
|
||||
OMAP_MCBSP_WRITE(io_base, RCCR, w);
|
||||
}
|
||||
w = OMAP_MCBSP_READ(io_base, SPCR1);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1));
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~rx);
|
||||
|
||||
/* Reset the sample rate generator */
|
||||
w = OMAP_MCBSP_READ(io_base, SPCR2);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
|
||||
idle = !((OMAP_MCBSP_READ(io_base, SPCR2) |
|
||||
OMAP_MCBSP_READ(io_base, SPCR1)) & 1);
|
||||
|
||||
if (idle) {
|
||||
/* Reset the sample rate generator */
|
||||
w = OMAP_MCBSP_READ(io_base, SPCR2);
|
||||
OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(omap_mcbsp_stop);
|
||||
|
||||
|
|
@ -883,6 +1097,149 @@ void omap_mcbsp_set_spi_mode(unsigned int id,
|
|||
}
|
||||
EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP34XX
|
||||
#define max_thres(m) (mcbsp->pdata->buffer_size)
|
||||
#define valid_threshold(m, val) ((val) <= max_thres(m))
|
||||
#define THRESHOLD_PROP_BUILDER(prop) \
|
||||
static ssize_t prop##_show(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \
|
||||
\
|
||||
return sprintf(buf, "%u\n", mcbsp->prop); \
|
||||
} \
|
||||
\
|
||||
static ssize_t prop##_store(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t size) \
|
||||
{ \
|
||||
struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \
|
||||
unsigned long val; \
|
||||
int status; \
|
||||
\
|
||||
status = strict_strtoul(buf, 0, &val); \
|
||||
if (status) \
|
||||
return status; \
|
||||
\
|
||||
if (!valid_threshold(mcbsp, val)) \
|
||||
return -EDOM; \
|
||||
\
|
||||
mcbsp->prop = val; \
|
||||
return size; \
|
||||
} \
|
||||
\
|
||||
static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store);
|
||||
|
||||
THRESHOLD_PROP_BUILDER(max_tx_thres);
|
||||
THRESHOLD_PROP_BUILDER(max_rx_thres);
|
||||
|
||||
static const char *dma_op_modes[] = {
|
||||
"element", "threshold", "frame",
|
||||
};
|
||||
|
||||
static ssize_t dma_op_mode_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
|
||||
int dma_op_mode, i = 0;
|
||||
ssize_t len = 0;
|
||||
const char * const *s;
|
||||
|
||||
spin_lock_irq(&mcbsp->lock);
|
||||
dma_op_mode = mcbsp->dma_op_mode;
|
||||
spin_unlock_irq(&mcbsp->lock);
|
||||
|
||||
for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) {
|
||||
if (dma_op_mode == i)
|
||||
len += sprintf(buf + len, "[%s] ", *s);
|
||||
else
|
||||
len += sprintf(buf + len, "%s ", *s);
|
||||
}
|
||||
len += sprintf(buf + len, "\n");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t dma_op_mode_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
|
||||
const char * const *s;
|
||||
int i = 0;
|
||||
|
||||
for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++)
|
||||
if (sysfs_streq(buf, *s))
|
||||
break;
|
||||
|
||||
if (i == ARRAY_SIZE(dma_op_modes))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irq(&mcbsp->lock);
|
||||
if (!mcbsp->free) {
|
||||
size = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
mcbsp->dma_op_mode = i;
|
||||
|
||||
unlock:
|
||||
spin_unlock_irq(&mcbsp->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store);
|
||||
|
||||
static const struct attribute *additional_attrs[] = {
|
||||
&dev_attr_max_tx_thres.attr,
|
||||
&dev_attr_max_rx_thres.attr,
|
||||
&dev_attr_dma_op_mode.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group additional_attr_group = {
|
||||
.attrs = (struct attribute **)additional_attrs,
|
||||
};
|
||||
|
||||
static inline int __devinit omap_additional_add(struct device *dev)
|
||||
{
|
||||
return sysfs_create_group(&dev->kobj, &additional_attr_group);
|
||||
}
|
||||
|
||||
static inline void __devexit omap_additional_remove(struct device *dev)
|
||||
{
|
||||
sysfs_remove_group(&dev->kobj, &additional_attr_group);
|
||||
}
|
||||
|
||||
static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp)
|
||||
{
|
||||
mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
|
||||
if (cpu_is_omap34xx()) {
|
||||
mcbsp->max_tx_thres = max_thres(mcbsp);
|
||||
mcbsp->max_rx_thres = max_thres(mcbsp);
|
||||
/*
|
||||
* REVISIT: Set dmap_op_mode to THRESHOLD as default
|
||||
* for mcbsp2 instances.
|
||||
*/
|
||||
if (omap_additional_add(mcbsp->dev))
|
||||
dev_warn(mcbsp->dev,
|
||||
"Unable to create additional controls\n");
|
||||
} else {
|
||||
mcbsp->max_tx_thres = -EINVAL;
|
||||
mcbsp->max_rx_thres = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp)
|
||||
{
|
||||
if (cpu_is_omap34xx())
|
||||
omap_additional_remove(mcbsp->dev);
|
||||
}
|
||||
#else
|
||||
static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {}
|
||||
static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {}
|
||||
#endif /* CONFIG_ARCH_OMAP34XX */
|
||||
|
||||
/*
|
||||
* McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
|
||||
* 730 has only 2 McBSP, and both of them are MPU peripherals.
|
||||
|
|
@ -953,6 +1310,10 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
|
|||
mcbsp->dev = &pdev->dev;
|
||||
mcbsp_ptr[id] = mcbsp;
|
||||
platform_set_drvdata(pdev, mcbsp);
|
||||
|
||||
/* Initialize mcbsp properties for OMAP34XX if needed / applicable */
|
||||
omap34xx_device_init(mcbsp);
|
||||
|
||||
return 0;
|
||||
|
||||
err_fclk:
|
||||
|
|
@ -976,6 +1337,8 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
|
|||
mcbsp->pdata->ops->free)
|
||||
mcbsp->pdata->ops->free(mcbsp->id);
|
||||
|
||||
omap34xx_device_exit(mcbsp);
|
||||
|
||||
clk_disable(mcbsp->fclk);
|
||||
clk_disable(mcbsp->iclk);
|
||||
clk_put(mcbsp->fclk);
|
||||
|
|
|
|||
37
arch/arm/plat-s3c/include/plat/audio-simtec.h
Normal file
37
arch/arm/plat-s3c/include/plat/audio-simtec.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* arch/arm/plat-s3c/include/plat/audio-simtec.h
|
||||
*
|
||||
* Copyright 2008 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Simtec Audio support.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct s3c24xx_audio_simtec_pdata - platform data for simtec audio
|
||||
* @use_mpllin: Select codec clock from MPLLin
|
||||
* @output_cdclk: Need to output CDCLK to the codec
|
||||
* @have_mic: Set if we have a MIC socket
|
||||
* @have_lout: Set if we have a LineOut socket
|
||||
* @amp_gpio: GPIO pin to enable the AMP
|
||||
* @amp_gain: Option GPIO to control AMP gain
|
||||
*/
|
||||
struct s3c24xx_audio_simtec_pdata {
|
||||
unsigned int use_mpllin:1;
|
||||
unsigned int output_cdclk:1;
|
||||
|
||||
unsigned int have_mic:1;
|
||||
unsigned int have_lout:1;
|
||||
|
||||
int amp_gpio;
|
||||
int amp_gain[2];
|
||||
|
||||
void (*startup)(void);
|
||||
};
|
||||
|
||||
extern int simtec_audio_add(const char *codec_name,
|
||||
struct s3c24xx_audio_simtec_pdata *pdata);
|
||||
|
|
@ -33,6 +33,11 @@
|
|||
#define S3C2412_IISCON_RXDMA_ACTIVE (1 << 1)
|
||||
#define S3C2412_IISCON_IIS_ACTIVE (1 << 0)
|
||||
|
||||
#define S3C64XX_IISMOD_BLC_16BIT (0 << 13)
|
||||
#define S3C64XX_IISMOD_BLC_8BIT (1 << 13)
|
||||
#define S3C64XX_IISMOD_BLC_24BIT (2 << 13)
|
||||
#define S3C64XX_IISMOD_BLC_MASK (3 << 13)
|
||||
|
||||
#define S3C64XX_IISMOD_IMS_PCLK (0 << 10)
|
||||
#define S3C64XX_IISMOD_IMS_SYSMUX (1 << 10)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue