/*
* sound/soc/omap/mcbsp.c
*
* Copyright (C) 2004 Nokia Corporation
* Author: Samuel Ortiz <samuel.ortiz@nokia.com>
*
* Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
* Peter Ujfalusi <peter.ujfalusi@ti.com>
*
* 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.
*
* Multichannel mode not supported.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <plat/mcbsp.h>
#include "mcbsp.h"
static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
{
void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
if (mcbsp->pdata->reg_size == 2) {
((u16 *)mcbsp->reg_cache)[reg] = (u16)val;
__raw_writew((u16)val, addr);
} else {
((u32 *)mcbsp->reg_cache)[reg] = val;
__raw_writel(val, addr);
}
}
static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
{
void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
if (mcbsp->pdata->reg_size == 2) {
return !from_cache ? __raw_readw(addr) :
((u16 *)mcbsp->reg_cache)[reg];
} else {
return !from_cache ? __raw_readl(addr) :
((u32 *)mcbsp->reg_cache)[reg];
}
}
static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
{
__raw_writel(val, mcbsp->st_data->io_base_st + reg);
}
static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
{
return __raw_readl(mcbsp->st_data->io_base_st + reg);
}
#define MCBSP_READ(mcbsp, reg) \
omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0)
#define MCBSP_WRITE(mcbsp, reg, val) \
omap_mcbsp_write(mcbsp, OMAP_MCBSP_REG_##reg, val)
#define MCBSP_READ_CACHE(mcbsp, reg) \
omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 1)
#define MCBSP_ST_READ(mcbsp, reg) \
omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg)
#define MCBSP_ST_WRITE(mcbsp, reg, val) \
omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val)
static void omap_mcbsp_dump_reg(struct omap_mcbsp *mcbsp)
{
dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id);
dev_dbg(mcbsp->dev, "DRR2: 0x%04x\n",
MCBSP_READ(mcbsp, DRR2));
dev_dbg(mcbsp->dev, "DRR1: 0x%04x\n",
MCBSP_READ(mcbsp, DRR1));
dev_dbg(mcbsp->dev, "DXR2: 0x%04x\n",
MCBSP_READ(mcbsp, DXR2));
dev_dbg(mcbsp->dev, "DXR1: 0x%04x\n",
MCBSP_READ(mcbsp, DXR1));
dev_dbg(mcbsp->dev, "SPCR2: 0x%04x\n",
MCBSP_READ(mcbsp, SPCR2));
dev_dbg(mcbsp->dev, "SPCR1: 0x%04x\n",
MCBSP_READ(mcbsp, SPCR1));
dev_dbg(mcbsp->dev, "RCR2: 0x%04x\n",
MCBSP_READ(mcbsp, RCR2));
dev_dbg(mcbsp->dev, "RCR1: 0x%04x\n",
MCBSP_READ(mcbsp, RCR1));
dev_dbg(mcbsp->dev, "XCR2: 0x%04x\n",
MCBSP_READ(mcbsp, XCR2));
dev_dbg(mcbsp->dev, "XCR1: 0x%04x\n",
MCBSP_READ(mcbsp, XCR1));
dev_dbg(mcbsp->dev, "SRGR2: 0x%04x\n",
MCBSP_READ(mcbsp, SRGR2));
dev_dbg(mcbsp->dev, "SRGR1: 0x%04x\n",
MCBSP_READ(mcbsp, SRGR1));
dev_dbg(mcbsp->dev, "PCR0: 0x%04x\n",
MCBSP_READ(mcbsp, PCR0));
dev_dbg(mcbsp->dev, "***********************\n");
}
static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
{
struct omap_mcbsp *mcbsp_tx = dev_id;
u16 irqst_spcr2;
irqst_spcr2 = MCBSP_READ(mcbsp_tx, SPCR2);
dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", irqst_spcr2);
if (irqst_spcr2 & XSYNC_ERR)