/*
* linux/drivers/video/omap2/dss/rfbi.c
*
* Copyright (C) 2009 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
* Some code and ideas taken from drivers/video/omap/ driver
* by Imre Deak.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#define DSS_SUBSYS_NAME "RFBI"
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
#include <linux/export.h>
#include <linux/vmalloc.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/kfifo.h>
#include <linux/ktime.h>
#include <linux/hrtimer.h>
#include <linux/seq_file.h>
#include <linux/semaphore.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <video/omapdss.h>
#include "dss.h"
struct rfbi_reg { u16 idx; };
#define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
#define RFBI_REVISION RFBI_REG(0x0000)
#define RFBI_SYSCONFIG RFBI_REG(0x0010)
#define RFBI_SYSSTATUS RFBI_REG(0x0014)
#define RFBI_CONTROL RFBI_REG(0x0040)
#define RFBI_PIXEL_CNT RFBI_REG(0x0044)
#define RFBI_LINE_NUMBER RFBI_REG(0x0048)
#define RFBI_CMD RFBI_REG(0x004c)
#define RFBI_PARAM RFBI_REG(0x0050)
#define RFBI_DATA RFBI_REG(0x0054)
#define RFBI_READ RFBI_REG(0x0058)
#define RFBI_STATUS RFBI_REG(0x005c)
#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18)
#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18)
#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18)
#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18)
#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18)
#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18)
#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090)
#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094)
#define REG_FLD_MOD(idx, val, start, end) \
rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
enum omap_rfbi_cycleformat {
OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
};
enum omap_rfbi_datatype {
OMAP_DSS_RFBI_DATATYPE_12 = 0,
OMAP_DSS_RFBI_DATATYPE_16 = 1,
OMAP_DSS_RFBI_DATATYPE_18 = 2,
OMAP_DSS_RFBI_DATATYPE_24 = 3,
};
enum omap_rfbi_parallelmode {
OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
};
static int rfbi_convert_timings(struct rfbi_timings *t);
static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
static struct {
struct platform_device *pdev;
void __iomem *base;
unsigned long l4_khz;
enum omap_rfbi_datatype datatype;
enum omap_rfbi_parallelmode parallelmode;
enum omap_rfbi_te_mode te_mode;
int te_enabled;
void (*framedone_callback)(void *data);
void *framedone_callback_data;
struct omap_dss_device *dssdev[2];
struct semaphore bus_lock;
} rfbi;
static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
{
__raw_writel(val, rfbi.base + idx.idx);
}
static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
{
return __raw_readl(rfbi.base + idx.idx);
}
static int rfbi_runtime_get(void)
{
int r;
DSSDBG("rfbi_runtime_get\n");
r = pm_runtime_get_sync(&rfbi.pdev->dev);
WARN_ON(r < 0);
return r < 0 ? r : 0;
}
static void rfbi_runtime_put(void)
{
int r;
DSSDBG("rfbi_runtime_put\n");
r = pm_runtime_put(&rfbi.pdev->dev);
WARN_ON(r < 0);
}
void rfbi_bus_lock(void)
{
down(&rfbi.bus_lock);
}
EXPORT_SYMBOL(rfbi_bus_lock);
void rfbi_bus_unlock(void)
{
up(&rfbi.bus_lock);
}
EXPORT_SYMBOL(rfbi_bus_unlock);
void omap_rfbi_write_command(const void *buf, u32 len)
{
switch (rfbi.parallelmode) {
case OMAP_DSS_RFBI_PARALLELMODE_8:
{
const u8 *b = buf;
for (; len; len--)
rfbi_write_reg(RFBI_CMD, *b++);
break;
}
case OMAP_DSS_RFBI_PARALLELMODE_16:
{
const u16 *w = buf;
BUG_ON(len & 1);
for (; len; len -= 2)
rfbi_write_reg(RFBI_CMD, *w++);
break;
}
case OMAP_DSS_RFBI_PARALLELMODE_9:
case OMAP_DSS_RFBI_PARALLELMODE_12:
default:
BUG();
}
}
EXPORT_SYMBOL(omap_rfbi_write_command);
void omap_rfbi_read_data(void *buf, u32 len)
{
switch (rfbi.parallelmode) {
case OMAP_DSS_RFBI_PARALLELMODE_8:
{
u8