336 lines
7.8 KiB
C
336 lines
7.8 KiB
C
|
/* linux/drivers/video/fbdev/exynos/dpu/dpp.h
|
||
|
*
|
||
|
* Copyright (c) 2016 Samsung Electronics Co., Ltd.
|
||
|
*
|
||
|
* header file for Samsung EXYNOS SoC DPP driver
|
||
|
*
|
||
|
* 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.
|
||
|
*/
|
||
|
|
||
|
#ifndef __SAMSUNG_DPP_H__
|
||
|
#define __SAMSUNG_DPP_H__
|
||
|
|
||
|
#include <linux/delay.h>
|
||
|
#include <linux/sched.h>
|
||
|
#include <linux/spinlock.h>
|
||
|
#include <linux/types.h>
|
||
|
#include <linux/videodev2.h>
|
||
|
#include <linux/io.h>
|
||
|
#include <linux/pm_runtime.h>
|
||
|
#include <linux/pm_qos.h>
|
||
|
#include <linux/of.h>
|
||
|
#include <linux/of_address.h>
|
||
|
#if defined(CONFIG_SUPPORT_LEGACY_ION)
|
||
|
#include <linux/exynos_iovmm.h>
|
||
|
#else
|
||
|
#include <linux/ion_exynos.h>
|
||
|
#endif
|
||
|
#if defined(CONFIG_EXYNOS_BTS)
|
||
|
#include <soc/samsung/bts.h>
|
||
|
#endif
|
||
|
|
||
|
#include "decon.h"
|
||
|
/* TODO: SoC dependency will be removed */
|
||
|
#if defined(CONFIG_SOC_EXYNOS9610)
|
||
|
#include "./cal_9610/regs-dpp.h"
|
||
|
#include "./cal_9610/dpp_cal.h"
|
||
|
#endif
|
||
|
|
||
|
extern int dpp_log_level;
|
||
|
|
||
|
#define DPP_MODULE_NAME "exynos-dpp"
|
||
|
#define MAX_DPP_CNT 5 /* + ODMA case */
|
||
|
|
||
|
/* about 1msec @ ACLK=630MHz */
|
||
|
#define INIT_RCV_NUM 630000
|
||
|
|
||
|
#define check_align(width, height, align_w, align_h)\
|
||
|
(IS_ALIGNED(width, align_w) && IS_ALIGNED(height, align_h))
|
||
|
|
||
|
#define is_normal(config) (DPP_ROT_NORMAL)
|
||
|
#define is_rotation(config) (config->dpp_parm.rot > DPP_ROT_180)
|
||
|
#define is_yuv(config) ((config->format >= DECON_PIXEL_FORMAT_NV16) \
|
||
|
&& (config->format < DECON_PIXEL_FORMAT_MAX))
|
||
|
#define is_yuv422(config) ((config->format >= DECON_PIXEL_FORMAT_NV16) \
|
||
|
&& (config->format <= DECON_PIXEL_FORMAT_YVU422_3P))
|
||
|
#define is_yuv420(config) ((config->format >= DECON_PIXEL_FORMAT_NV12) \
|
||
|
&& (config->format <= DECON_PIXEL_FORMAT_YVU420M))
|
||
|
|
||
|
#define dpp_err(fmt, ...) \
|
||
|
do { \
|
||
|
if (dpp_log_level >= 3) { \
|
||
|
pr_err(pr_fmt("decon: "fmt), ##__VA_ARGS__); \
|
||
|
} \
|
||
|
} while (0)
|
||
|
|
||
|
#define dpp_warn(fmt, ...) \
|
||
|
do { \
|
||
|
if (dpp_log_level >= 4) { \
|
||
|
pr_warn(pr_fmt("decon: "fmt), ##__VA_ARGS__); \
|
||
|
} \
|
||
|
} while (0)
|
||
|
|
||
|
#define dpp_info(fmt, ...) \
|
||
|
do { \
|
||
|
if (dpp_log_level >= 6) \
|
||
|
pr_info(pr_fmt("decon: "fmt), ##__VA_ARGS__); \
|
||
|
} while (0)
|
||
|
|
||
|
#define dpp_dbg(fmt, ...) \
|
||
|
do { \
|
||
|
if (dpp_log_level >= 7) \
|
||
|
pr_info(pr_fmt("decon: "fmt), ##__VA_ARGS__); \
|
||
|
} while (0)
|
||
|
|
||
|
/* TODO: This will be removed */
|
||
|
|
||
|
enum dpp_csc_defs {
|
||
|
/* csc_type */
|
||
|
DPP_CSC_BT_601 = 0,
|
||
|
DPP_CSC_BT_709 = 1,
|
||
|
/* csc_range */
|
||
|
DPP_CSC_NARROW = 0,
|
||
|
DPP_CSC_WIDE = 1,
|
||
|
/* csc_mode */
|
||
|
CSC_COEF_HARDWIRED = 0,
|
||
|
CSC_COEF_CUSTOMIZED = 1,
|
||
|
/* csc_id used in csc_3x3_t[] : increase by even value */
|
||
|
DPP_CSC_ID_BT_2020 = 0,
|
||
|
DPP_CSC_ID_DCI_P3 = 2,
|
||
|
};
|
||
|
|
||
|
enum dpp_state {
|
||
|
DPP_STATE_ON,
|
||
|
DPP_STATE_OFF,
|
||
|
};
|
||
|
|
||
|
enum dpp_reg_area {
|
||
|
REG_AREA_DPP = 0,
|
||
|
REG_AREA_DMA,
|
||
|
REG_AREA_DMA_COM,
|
||
|
};
|
||
|
|
||
|
enum dpp_attr {
|
||
|
DPP_ATTR_AFBC = 0,
|
||
|
DPP_ATTR_BLOCK = 1,
|
||
|
DPP_ATTR_FLIP = 2,
|
||
|
DPP_ATTR_ROT = 3,
|
||
|
DPP_ATTR_CSC = 4,
|
||
|
DPP_ATTR_SCALE = 5,
|
||
|
DPP_ATTR_HDR = 6,
|
||
|
DPP_ATTR_HDR10 = 7,
|
||
|
|
||
|
DPP_ATTR_IDMA = 16,
|
||
|
DPP_ATTR_ODMA = 17,
|
||
|
DPP_ATTR_DPP = 18,
|
||
|
};
|
||
|
|
||
|
struct dpp_resources {
|
||
|
struct clk *gate;
|
||
|
void __iomem *regs;
|
||
|
void __iomem *dma_regs;
|
||
|
void __iomem *dma_com_regs;
|
||
|
int irq;
|
||
|
int dma_irq;
|
||
|
};
|
||
|
|
||
|
struct dpp_debug {
|
||
|
struct timer_list op_timer;
|
||
|
u32 done_count;
|
||
|
u32 recovery_cnt;
|
||
|
};
|
||
|
|
||
|
struct dpp_config {
|
||
|
struct decon_win_config config;
|
||
|
unsigned long rcv_num;
|
||
|
};
|
||
|
|
||
|
struct dpp_size_range {
|
||
|
u32 min;
|
||
|
u32 max;
|
||
|
u32 align;
|
||
|
};
|
||
|
|
||
|
struct dpp_restriction {
|
||
|
struct dpp_size_range src_f_w;
|
||
|
struct dpp_size_range src_f_h;
|
||
|
struct dpp_size_range src_w;
|
||
|
struct dpp_size_range src_h;
|
||
|
u32 src_x_align;
|
||
|
u32 src_y_align;
|
||
|
|
||
|
struct dpp_size_range dst_f_w;
|
||
|
struct dpp_size_range dst_f_h;
|
||
|
struct dpp_size_range dst_w;
|
||
|
struct dpp_size_range dst_h;
|
||
|
u32 dst_x_align;
|
||
|
u32 dst_y_align;
|
||
|
|
||
|
struct dpp_size_range blk_w;
|
||
|
struct dpp_size_range blk_h;
|
||
|
u32 blk_x_align;
|
||
|
u32 blk_y_align;
|
||
|
|
||
|
u32 src_h_rot_max; /* limit of source img height in case of rotation */
|
||
|
|
||
|
u32 *format; /* supported format list for each DPP channel */
|
||
|
u32 reserved[8];
|
||
|
};
|
||
|
|
||
|
struct dpp_ch_restriction {
|
||
|
int id;
|
||
|
unsigned long attr;
|
||
|
|
||
|
struct dpp_restriction restriction;
|
||
|
u32 reserved[4];
|
||
|
};
|
||
|
|
||
|
struct dpp_restrictions_info {
|
||
|
u32 ver; /* version of dpp_restrictions_info structure */
|
||
|
struct dpp_ch_restriction dpp_ch[MAX_DPP_CNT];
|
||
|
u32 reserved[4];
|
||
|
};
|
||
|
|
||
|
struct dpp_device {
|
||
|
int id;
|
||
|
int port;
|
||
|
unsigned long attr;
|
||
|
enum dpp_state state;
|
||
|
struct device *dev;
|
||
|
struct v4l2_subdev sd;
|
||
|
struct dpp_resources res;
|
||
|
struct dpp_debug d;
|
||
|
wait_queue_head_t framedone_wq;
|
||
|
struct dpp_config *dpp_config;
|
||
|
spinlock_t slock;
|
||
|
spinlock_t dma_slock;
|
||
|
struct mutex lock;
|
||
|
struct dpp_restriction restriction;
|
||
|
};
|
||
|
|
||
|
extern struct dpp_device *dpp_drvdata[MAX_DPP_CNT];
|
||
|
|
||
|
static inline struct dpp_device *get_dpp_drvdata(u32 id)
|
||
|
{
|
||
|
return dpp_drvdata[id];
|
||
|
}
|
||
|
|
||
|
static inline u32 dpp_read(u32 id, u32 reg_id)
|
||
|
{
|
||
|
struct dpp_device *dpp = get_dpp_drvdata(id);
|
||
|
return readl(dpp->res.regs + reg_id);
|
||
|
}
|
||
|
|
||
|
static inline u32 dpp_read_mask(u32 id, u32 reg_id, u32 mask)
|
||
|
{
|
||
|
u32 val = dpp_read(id, reg_id);
|
||
|
val &= (~mask);
|
||
|
return val;
|
||
|
}
|
||
|
|
||
|
static inline void dpp_write(u32 id, u32 reg_id, u32 val)
|
||
|
{
|
||
|
struct dpp_device *dpp = get_dpp_drvdata(id);
|
||
|
writel(val, dpp->res.regs + reg_id);
|
||
|
}
|
||
|
|
||
|
static inline void dpp_write_mask(u32 id, u32 reg_id, u32 val, u32 mask)
|
||
|
{
|
||
|
struct dpp_device *dpp = get_dpp_drvdata(id);
|
||
|
u32 old = dpp_read(id, reg_id);
|
||
|
|
||
|
val = (val & mask) | (old & ~mask);
|
||
|
writel(val, dpp->res.regs + reg_id);
|
||
|
}
|
||
|
|
||
|
/* DPU_DMA Common part */
|
||
|
static inline u32 dma_com_read(u32 id, u32 reg_id)
|
||
|
{
|
||
|
struct dpp_device *dpp = get_dpp_drvdata(0);
|
||
|
return readl(dpp->res.dma_com_regs + reg_id);
|
||
|
}
|
||
|
|
||
|
static inline u32 dma_com_read_mask(u32 id, u32 reg_id, u32 mask)
|
||
|
{
|
||
|
u32 val = dma_com_read(id, reg_id);
|
||
|
val &= (~mask);
|
||
|
return val;
|
||
|
}
|
||
|
|
||
|
static inline void dma_com_write(u32 id, u32 reg_id, u32 val)
|
||
|
{
|
||
|
/* get reliable address when probing IDMA_G0 */
|
||
|
struct dpp_device *dpp = get_dpp_drvdata(0);
|
||
|
writel(val, dpp->res.dma_com_regs + reg_id);
|
||
|
}
|
||
|
|
||
|
static inline void dma_com_write_mask(u32 id, u32 reg_id, u32 val, u32 mask)
|
||
|
{
|
||
|
struct dpp_device *dpp = get_dpp_drvdata(0);
|
||
|
u32 old = dma_com_read(id, reg_id);
|
||
|
|
||
|
val = (val & mask) | (old & ~mask);
|
||
|
writel(val, dpp->res.dma_com_regs + reg_id);
|
||
|
}
|
||
|
|
||
|
/* DPU_DMA */
|
||
|
static inline u32 dma_read(u32 id, u32 reg_id)
|
||
|
{
|
||
|
struct dpp_device *dpp = get_dpp_drvdata(id);
|
||
|
return readl(dpp->res.dma_regs + reg_id);
|
||
|
}
|
||
|
|
||
|
static inline u32 dma_read_mask(u32 id, u32 reg_id, u32 mask)
|
||
|
{
|
||
|
u32 val = dma_read(id, reg_id);
|
||
|
val &= (~mask);
|
||
|
return val;
|
||
|
}
|
||
|
|
||
|
static inline void dma_write(u32 id, u32 reg_id, u32 val)
|
||
|
{
|
||
|
struct dpp_device *dpp = get_dpp_drvdata(id);
|
||
|
writel(val, dpp->res.dma_regs + reg_id);
|
||
|
}
|
||
|
|
||
|
static inline void dma_write_mask(u32 id, u32 reg_id, u32 val, u32 mask)
|
||
|
{
|
||
|
struct dpp_device *dpp = get_dpp_drvdata(id);
|
||
|
u32 old = dma_read(id, reg_id);
|
||
|
|
||
|
val = (val & mask) | (old & ~mask);
|
||
|
writel(val, dpp->res.dma_regs + reg_id);
|
||
|
}
|
||
|
|
||
|
static inline void dpp_select_format(struct dpp_device *dpp,
|
||
|
struct dpp_img_format *vi, struct dpp_params_info *p)
|
||
|
{
|
||
|
struct decon_win_config *config = &dpp->dpp_config->config;
|
||
|
|
||
|
vi->normal = is_normal(dpp);
|
||
|
vi->rot = p->rot;
|
||
|
vi->scale = p->is_scale;
|
||
|
vi->format = p->format;
|
||
|
vi->afbc_en = p->is_comp;
|
||
|
vi->yuv = is_yuv(config);
|
||
|
vi->yuv422 = is_yuv422(config);
|
||
|
vi->yuv420 = is_yuv420(config);
|
||
|
vi->wb = test_bit(DPP_ATTR_ODMA, &dpp->attr);
|
||
|
}
|
||
|
|
||
|
void dpp_dump(struct dpp_device *dpp);
|
||
|
|
||
|
#define DPP_WIN_CONFIG _IOW('P', 0, struct decon_win_config)
|
||
|
#define DPP_STOP _IOW('P', 1, unsigned long)
|
||
|
#define DPP_DUMP _IOW('P', 2, u32)
|
||
|
#define DPP_WB_WAIT_FOR_FRAMEDONE _IOR('P', 3, u32)
|
||
|
#define DPP_WAIT_IDLE _IOR('P', 4, unsigned long)
|
||
|
#define DPP_SET_RECOVERY_NUM _IOR('P', 5, unsigned long)
|
||
|
#define DPP_AFBC_ATTR_ENABLED _IOR('P', 6, unsigned long)
|
||
|
#define DPP_GET_PORT_NUM _IOR('P', 7, unsigned long)
|
||
|
#define DPP_GET_RESTRICTION _IOR('P', 8, unsigned long)
|
||
|
|
||
|
#endif /* __SAMSUNG_DPP_H__ */
|