Commit 548aafcd authored by Sylwester Nawrocki's avatar Sylwester Nawrocki Committed by Mauro Carvalho Chehab

[media] s5p-fimc: mem2mem driver refactoring and cleanup

Register access functions refactored for camera capture interface
control. Removed the workqueue since it was only useful for FIFO
output mode which is not supported at this time.
Fixed errors on module unload. Comments and whitespace cleanup.
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 77e62082
This diff is collapsed.
......@@ -34,6 +34,7 @@
#define FIMC_MAX_OUT_BUFS 4
#define SCALER_MAX_HRATIO 64
#define SCALER_MAX_VRATIO 64
#define DMA_MIN_SIZE 8
enum {
ST_IDLE,
......@@ -54,21 +55,21 @@ enum fimc_datapath {
};
enum fimc_color_fmt {
S5P_FIMC_RGB565,
S5P_FIMC_RGB565 = 0x10,
S5P_FIMC_RGB666,
S5P_FIMC_RGB888,
S5P_FIMC_YCBCR420,
S5P_FIMC_RGB30_LOCAL,
S5P_FIMC_YCBCR420 = 0x20,
S5P_FIMC_YCBCR422,
S5P_FIMC_YCBYCR422,
S5P_FIMC_YCRYCB422,
S5P_FIMC_CBYCRY422,
S5P_FIMC_CRYCBY422,
S5P_FIMC_RGB30_LOCAL,
S5P_FIMC_YCBCR444_LOCAL,
S5P_FIMC_MAX_COLOR = S5P_FIMC_YCBCR444_LOCAL,
S5P_FIMC_COLOR_MASK = 0x0F,
};
#define fimc_fmt_is_rgb(x) ((x) & 0x10)
/* Y/Cb/Cr components order at DMA output for 1 plane YCbCr 4:2:2 formats. */
#define S5P_FIMC_OUT_CRYCBY S5P_CIOCTRL_ORDER422_CRYCBY
#define S5P_FIMC_OUT_CBYCRY S5P_CIOCTRL_ORDER422_YCRYCB
......@@ -93,11 +94,13 @@ enum fimc_color_fmt {
#define S5P_FIMC_EFFECT_SIKHOUETTE S5P_CIIMGEFF_FIN_SILHOUETTE
/* The hardware context state. */
#define FIMC_PARAMS (1 << 0)
#define FIMC_SRC_ADDR (1 << 1)
#define FIMC_DST_ADDR (1 << 2)
#define FIMC_SRC_FMT (1 << 3)
#define FIMC_DST_FMT (1 << 4)
#define FIMC_PARAMS (1 << 0)
#define FIMC_SRC_ADDR (1 << 1)
#define FIMC_DST_ADDR (1 << 2)
#define FIMC_SRC_FMT (1 << 3)
#define FIMC_DST_FMT (1 << 4)
#define FIMC_CTX_M2M (1 << 5)
#define FIMC_CTX_CAP (1 << 6)
/* Image conversion flags */
#define FIMC_IN_DMA_ACCESS_TILED (1 << 0)
......@@ -106,7 +109,9 @@ enum fimc_color_fmt {
#define FIMC_OUT_DMA_ACCESS_LINEAR (0 << 1)
#define FIMC_SCAN_MODE_PROGRESSIVE (0 << 2)
#define FIMC_SCAN_MODE_INTERLACED (1 << 2)
/* YCbCr data dynamic range for RGB-YUV color conversion. Y/Cb/Cr: (0 ~ 255) */
/*
* YCbCr data dynamic range for RGB-YUV color conversion.
* Y/Cb/Cr: (0 ~ 255) */
#define FIMC_COLOR_RANGE_WIDE (0 << 3)
/* Y (16 ~ 235), Cb/Cr (16 ~ 240) */
#define FIMC_COLOR_RANGE_NARROW (1 << 3)
......@@ -167,37 +172,37 @@ struct fimc_effect {
/**
* struct fimc_scaler - the configuration data for FIMC inetrnal scaler
*
* @enabled: the flag set when the scaler is used
* @scaleup_h: flag indicating scaling up horizontally
* @scaleup_v: flag indicating scaling up vertically
* @copy_mode: flag indicating transparent DMA transfer (no scaling
* and color format conversion)
* @enabled: flag indicating if the scaler is used
* @hfactor: horizontal shift factor
* @vfactor: vertical shift factor
* @pre_hratio: horizontal ratio of the prescaler
* @pre_vratio: vertical ratio of the prescaler
* @pre_dst_width: the prescaler's destination width
* @pre_dst_height: the prescaler's destination height
* @scaleup_h: flag indicating scaling up horizontally
* @scaleup_v: flag indicating scaling up vertically
* @main_hratio: the main scaler's horizontal ratio
* @main_vratio: the main scaler's vertical ratio
* @real_width: source width - offset
* @real_height: source height - offset
* @copy_mode: flag set if one-to-one mode is used, i.e. no scaling
* and color format conversion
* @real_width: source pixel (width - offset)
* @real_height: source pixel (height - offset)
*/
struct fimc_scaler {
u32 enabled;
int scaleup_h:1;
int scaleup_v:1;
int copy_mode:1;
int enabled:1;
u32 hfactor;
u32 vfactor;
u32 pre_hratio;
u32 pre_vratio;
u32 pre_dst_width;
u32 pre_dst_height;
u32 scaleup_h;
u32 scaleup_v;
u32 main_hratio;
u32 main_vratio;
u32 real_width;
u32 real_height;
u32 copy_mode;
};
/**
......@@ -222,8 +227,7 @@ struct fimc_vid_buffer {
};
/**
* struct fimc_frame - input/output frame format properties
*
* struct fimc_frame - source/target frame properties
* @f_width: image full width (virtual screen size)
* @f_height: image full height (virtual screen size)
* @o_width: original image width as set by S_FMT
......@@ -279,10 +283,10 @@ struct fimc_m2m_device {
* @min_out_pixsize: minimum output pixel size
* @scaler_en_w: maximum input pixel width when the scaler is enabled
* @scaler_dis_w: maximum input pixel width when the scaler is disabled
* @in_rot_en_h: maximum input width when the input rotator is used
* @in_rot_dis_w: maximum input width when the input rotator is used
* @out_rot_en_w: maximum output width for the output rotator enabled
* @out_rot_dis_w: maximum output width for the output rotator enabled
* @in_rot_en_h: maximum input width when the input rotator is enabled
* @in_rot_dis_w: maximum input width when the input rotator is disabled
* @out_rot_en_w: maximum target width when the output rotator enabled
* @out_rot_dis_w: maximum target width when the output rotator disnabled
*/
struct samsung_fimc_variant {
unsigned int pix_hoff:1;
......@@ -300,7 +304,7 @@ struct samsung_fimc_variant {
};
/**
* struct samsung_fimc_driverdata - per-device type driver data for init time.
* struct samsung_fimc_driverdata - per device type driver data for init time.
*
* @variant: the variant information for this driver.
* @dev_cnt: number of fimc sub-devices available in SoC
......@@ -313,7 +317,7 @@ struct samsung_fimc_driverdata {
struct fimc_ctx;
/**
* struct fimc_subdev - abstraction for a FIMC entity
* struct fimc_dev - abstraction for FIMC entity
*
* @slock: the spinlock protecting this data structure
* @lock: the mutex protecting this data structure
......@@ -323,7 +327,7 @@ struct fimc_ctx;
* @regs: the mapped hardware registers
* @regs_res: the resource claimed for IO registers
* @irq: interrupt number of the FIMC subdevice
* @irqlock: spinlock protecting videbuffer queue
* @irqlock: spinlock protecting videobuffer queue
* @m2m: memory-to-memory V4L2 device information
* @state: the FIMC device state flags
*/
......@@ -338,7 +342,6 @@ struct fimc_dev {
struct resource *regs_res;
int irq;
spinlock_t irqlock;
struct workqueue_struct *work_queue;
struct fimc_m2m_device m2m;
unsigned long state;
};
......@@ -359,7 +362,7 @@ struct fimc_dev {
* @effect: image effect
* @rotation: image clockwise rotation in degrees
* @flip: image flip mode
* @flags: an additional flags for image conversion
* @flags: additional flags for image conversion
* @state: flags to keep track of user configuration
* @fimc_dev: the FIMC device this context applies to
* @m2m_ctx: memory-to-memory device context
......@@ -397,18 +400,24 @@ static inline void fimc_hw_clear_irq(struct fimc_dev *dev)
writel(cfg, dev->regs + S5P_CIGCTRL);
}
static inline void fimc_hw_start_scaler(struct fimc_dev *dev)
static inline void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on)
{
u32 cfg = readl(dev->regs + S5P_CISCCTRL);
cfg |= S5P_CISCCTRL_SCALERSTART;
if (on)
cfg |= S5P_CISCCTRL_SCALERSTART;
else
cfg &= ~S5P_CISCCTRL_SCALERSTART;
writel(cfg, dev->regs + S5P_CISCCTRL);
}
static inline void fimc_hw_stop_scaler(struct fimc_dev *dev)
static inline void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on)
{
u32 cfg = readl(dev->regs + S5P_CISCCTRL);
cfg &= ~S5P_CISCCTRL_SCALERSTART;
writel(cfg, dev->regs + S5P_CISCCTRL);
u32 cfg = readl(dev->regs + S5P_MSCTRL);
if (on)
cfg |= S5P_MSCTRL_ENVID;
else
cfg &= ~S5P_MSCTRL_ENVID;
writel(cfg, dev->regs + S5P_MSCTRL);
}
static inline void fimc_hw_dis_capture(struct fimc_dev *dev)
......@@ -418,22 +427,8 @@ static inline void fimc_hw_dis_capture(struct fimc_dev *dev)
writel(cfg, dev->regs + S5P_CIIMGCPT);
}
static inline void fimc_hw_start_in_dma(struct fimc_dev *dev)
{
u32 cfg = readl(dev->regs + S5P_MSCTRL);
cfg |= S5P_MSCTRL_ENVID;
writel(cfg, dev->regs + S5P_MSCTRL);
}
static inline void fimc_hw_stop_in_dma(struct fimc_dev *dev)
{
u32 cfg = readl(dev->regs + S5P_MSCTRL);
cfg &= ~S5P_MSCTRL_ENVID;
writel(cfg, dev->regs + S5P_MSCTRL);
}
static inline struct fimc_frame *ctx_m2m_get_frame(struct fimc_ctx *ctx,
enum v4l2_buf_type type)
static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
enum v4l2_buf_type type)
{
struct fimc_frame *frame;
......@@ -452,20 +447,35 @@ static inline struct fimc_frame *ctx_m2m_get_frame(struct fimc_ctx *ctx,
/* -----------------------------------------------------*/
/* fimc-reg.c */
void fimc_hw_reset(struct fimc_dev *dev);
void fimc_hw_reset(struct fimc_dev *fimc);
void fimc_hw_set_rotation(struct fimc_ctx *ctx);
void fimc_hw_set_target_format(struct fimc_ctx *ctx);
void fimc_hw_set_out_dma(struct fimc_ctx *ctx);
void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable);
void fimc_hw_en_irq(struct fimc_dev *dev, int enable);
void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
void fimc_hw_en_lastirq(struct fimc_dev *fimc, int enable);
void fimc_hw_en_irq(struct fimc_dev *fimc, int enable);
void fimc_hw_set_scaler(struct fimc_ctx *ctx);
void fimc_hw_en_capture(struct fimc_ctx *ctx);
void fimc_hw_set_effect(struct fimc_ctx *ctx);
void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
void fimc_hw_set_input_path(struct fimc_ctx *ctx);
void fimc_hw_set_output_path(struct fimc_ctx *ctx);
void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr);
void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr);
void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr);
void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr,
int index);
/* Locking: the caller holds fimc->slock */
static inline void fimc_activate_capture(struct fimc_ctx *ctx)
{
fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled);
fimc_hw_en_capture(ctx);
}
static inline void fimc_deactivate_capture(struct fimc_dev *fimc)
{
fimc_hw_en_lastirq(fimc, true);
fimc_hw_dis_capture(fimc);
fimc_hw_enable_scaler(fimc, false);
fimc_hw_en_lastirq(fimc, false);
}
#endif /* FIMC_CORE_H_ */
......@@ -29,7 +29,7 @@ void fimc_hw_reset(struct fimc_dev *dev)
cfg = readl(dev->regs + S5P_CIGCTRL);
cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL);
writel(cfg, dev->regs + S5P_CIGCTRL);
msleep(1);
udelay(1000);
cfg = readl(dev->regs + S5P_CIGCTRL);
cfg &= ~S5P_CIGCTRL_SWRST;
......@@ -247,21 +247,20 @@ void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
spin_unlock_irqrestore(&dev->slock, flags);
}
void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
static void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
{
struct fimc_dev *dev = ctx->fimc_dev;
struct fimc_scaler *sc = &ctx->scaler;
u32 cfg = 0, shfactor;
u32 cfg, shfactor;
shfactor = 10 - (sc->hfactor + sc->vfactor);
cfg |= S5P_CISCPRERATIO_SHFACTOR(shfactor);
cfg = S5P_CISCPRERATIO_SHFACTOR(shfactor);
cfg |= S5P_CISCPRERATIO_HOR(sc->pre_hratio);
cfg |= S5P_CISCPRERATIO_VER(sc->pre_vratio);
writel(cfg, dev->regs + S5P_CISCPRERATIO);
cfg = 0;
cfg |= S5P_CISCPREDST_WIDTH(sc->pre_dst_width);
cfg = S5P_CISCPREDST_WIDTH(sc->pre_dst_width);
cfg |= S5P_CISCPREDST_HEIGHT(sc->pre_dst_height);
writel(cfg, dev->regs + S5P_CISCPREDST);
}
......@@ -274,6 +273,8 @@ void fimc_hw_set_scaler(struct fimc_ctx *ctx)
struct fimc_frame *dst_frame = &ctx->d_frame;
u32 cfg = 0;
fimc_hw_set_prescaler(ctx);
if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE);
......@@ -364,7 +365,7 @@ static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
u32 cfg_r = 0;
if (FIMC_LCDFIFO == ctx->out_path)
cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN;
cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN;
cfg_o |= S5P_ORIG_SIZE_HOR(frame->f_width);
cfg_o |= S5P_ORIG_SIZE_VER(frame->f_height);
......@@ -380,27 +381,25 @@ void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
struct fimc_dev *dev = ctx->fimc_dev;
struct fimc_frame *frame = &ctx->s_frame;
struct fimc_dma_offset *offset = &frame->dma_offset;
u32 cfg = 0;
u32 cfg;
/* Set the pixel offsets. */
cfg |= S5P_CIO_OFFS_HOR(offset->y_h);
cfg = S5P_CIO_OFFS_HOR(offset->y_h);
cfg |= S5P_CIO_OFFS_VER(offset->y_v);
writel(cfg, dev->regs + S5P_CIIYOFF);
cfg = 0;
cfg |= S5P_CIO_OFFS_HOR(offset->cb_h);
cfg = S5P_CIO_OFFS_HOR(offset->cb_h);
cfg |= S5P_CIO_OFFS_VER(offset->cb_v);
writel(cfg, dev->regs + S5P_CIICBOFF);
cfg = 0;
cfg |= S5P_CIO_OFFS_HOR(offset->cr_h);
cfg = S5P_CIO_OFFS_HOR(offset->cr_h);
cfg |= S5P_CIO_OFFS_VER(offset->cr_v);
writel(cfg, dev->regs + S5P_CIICROFF);
/* Input original and real size. */
fimc_hw_set_in_dma_size(ctx);
/* Autoload is used currently only in FIFO mode. */
/* Use DMA autoload only in FIFO mode. */
fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO);
/* Set the input DMA to process single frame only. */
......@@ -501,9 +500,7 @@ void fimc_hw_set_output_path(struct fimc_ctx *ctx)
void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
{
u32 cfg = 0;
cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
u32 cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DIS;
writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
......@@ -515,13 +512,15 @@ void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
}
void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
void fimc_hw_set_output_addr(struct fimc_dev *dev,
struct fimc_addr *paddr, int index)
{
int i;
/* Set all the output register sets to point to single video buffer. */
for (i = 0; i < FIMC_MAX_OUT_BUFS; i++) {
int i = (index == -1) ? 0 : index;
do {
writel(paddr->y, dev->regs + S5P_CIOYSA(i));
writel(paddr->cb, dev->regs + S5P_CIOCBSA(i));
writel(paddr->cr, dev->regs + S5P_CIOCRSA(i));
}
dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
i, paddr->y, paddr->cb, paddr->cr);
} while (index == -1 && ++i < FIMC_MAX_OUT_BUFS);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment