/* linux/drivers/media/video/exynos/rotator/rotator-regs.c * * Copyright (c) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * * Register interface file for Exynos Rotator 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. */ #include "rotator.h" void rot_hwset_irq_frame_done(struct rot_dev *rot, u32 enable) { unsigned long cfg = readl(rot->regs + ROTATOR_CONFIG); if (enable) cfg |= ROTATOR_CONFIG_IRQ_DONE; else cfg &= ~ROTATOR_CONFIG_IRQ_DONE; writel(cfg, rot->regs + ROTATOR_CONFIG); } void rot_hwset_irq_illegal_config(struct rot_dev *rot, u32 enable) { unsigned long cfg = readl(rot->regs + ROTATOR_CONFIG); if (enable) cfg |= ROTATOR_CONFIG_IRQ_ILLEGAL; else cfg &= ~ROTATOR_CONFIG_IRQ_ILLEGAL; writel(cfg, rot->regs + ROTATOR_CONFIG); } int rot_hwset_image_format(struct rot_dev *rot, u32 pixelformat) { unsigned long cfg = readl(rot->regs + ROTATOR_CONTROL); cfg &= ~ROTATOR_CONTROL_FMT_MASK; switch (pixelformat) { case V4L2_PIX_FMT_YUV420M: cfg |= ROTATOR_CONTROL_FMT_YCBCR420_3P; break; case V4L2_PIX_FMT_NV12M: cfg |= ROTATOR_CONTROL_FMT_YCBCR420_2P; break; case V4L2_PIX_FMT_YUYV: cfg |= ROTATOR_CONTROL_FMT_YCBCR422; break; case V4L2_PIX_FMT_RGB565: cfg |= ROTATOR_CONTROL_FMT_RGB565; break; case V4L2_PIX_FMT_RGB32: cfg |= ROTATOR_CONTROL_FMT_RGB888; break; default: rot_err("invalid pixelformat type\n"); return -EINVAL; } writel(cfg, rot->regs + ROTATOR_CONTROL); return 0; } void rot_hwset_flip(struct rot_dev *rot, u32 direction) { unsigned long cfg = readl(rot->regs + ROTATOR_CONTROL); cfg &= ~ROTATOR_CONTROL_FLIP_MASK; if (direction == ROT_VFLIP) cfg |= ROTATOR_CONTROL_FLIP_V; else if (direction == ROT_HFLIP) cfg |= ROTATOR_CONTROL_FLIP_H; writel(cfg, rot->regs + ROTATOR_CONTROL); } void rot_hwset_rotation(struct rot_dev *rot, int degree) { unsigned long cfg = readl(rot->regs + ROTATOR_CONTROL); cfg &= ~ROTATOR_CONTROL_ROT_MASK; if (degree == 90) cfg |= ROTATOR_CONTROL_ROT_90; else if (degree == 180) cfg |= ROTATOR_CONTROL_ROT_180; else if (degree == 270) cfg |= ROTATOR_CONTROL_ROT_270; writel(cfg, rot->regs + ROTATOR_CONTROL); } void rot_hwset_start(struct rot_dev *rot) { unsigned long cfg = readl(rot->regs + ROTATOR_CONTROL); cfg |= ROTATOR_CONTROL_START; writel(cfg, rot->regs + ROTATOR_CONTROL); } void rot_hwset_src_addr(struct rot_dev *rot, dma_addr_t addr, u32 comp) { writel(addr, rot->regs + ROTATOR_SRC_IMG_ADDR(comp)); } void rot_hwset_dst_addr(struct rot_dev *rot, dma_addr_t addr, u32 comp) { writel(addr, rot->regs + ROTATOR_DST_IMG_ADDR(comp)); } void rot_hwset_src_imgsize(struct rot_dev *rot, struct rot_frame *frame) { unsigned long cfg; cfg = ROTATOR_SRCIMG_YSIZE(frame->pix_mp.height) | ROTATOR_SRCIMG_XSIZE(frame->pix_mp.width); writel(cfg, rot->regs + ROTATOR_SRCIMG); cfg = ROTATOR_SRCROT_YSIZE(frame->pix_mp.height) | ROTATOR_SRCROT_XSIZE(frame->pix_mp.width); writel(cfg, rot->regs + ROTATOR_SRCROT); } void rot_hwset_src_crop(struct rot_dev *rot, struct v4l2_rect *rect) { unsigned long cfg; cfg = ROTATOR_SRC_Y(rect->top) | ROTATOR_SRC_X(rect->left); writel(cfg, rot->regs + ROTATOR_SRC); cfg = ROTATOR_SRCROT_YSIZE(rect->height) | ROTATOR_SRCROT_XSIZE(rect->width); writel(cfg, rot->regs + ROTATOR_SRCROT); } void rot_hwset_dst_imgsize(struct rot_dev *rot, struct rot_frame *frame) { unsigned long cfg; cfg = ROTATOR_DSTIMG_YSIZE(frame->pix_mp.height) | ROTATOR_DSTIMG_XSIZE(frame->pix_mp.width); writel(cfg, rot->regs + ROTATOR_DSTIMG); } void rot_hwset_dst_crop(struct rot_dev *rot, struct v4l2_rect *rect) { unsigned long cfg; cfg = ROTATOR_DST_Y(rect->top) | ROTATOR_DST_X(rect->left); writel(cfg, rot->regs + ROTATOR_DST); } void rot_hwget_irq_src(struct rot_dev *rot, enum rot_irq_src *irq) { unsigned long cfg = readl(rot->regs + ROTATOR_STATUS); cfg = ROTATOR_STATUS_IRQ(cfg); if (cfg == 1) *irq = ISR_PEND_DONE; else if (cfg == 2) *irq = ISR_PEND_ILLEGAL; } void rot_hwset_irq_clear(struct rot_dev *rot, enum rot_irq_src *irq) { unsigned long cfg = readl(rot->regs + ROTATOR_STATUS); cfg |= ROTATOR_STATUS_IRQ_PENDING((u32)irq); writel(cfg, rot->regs + ROTATOR_STATUS); } void rot_hwget_status(struct rot_dev *rot, enum rot_status *state) { unsigned long cfg; cfg = readl(rot->regs + ROTATOR_STATUS); cfg &= ROTATOR_STATUS_MASK; switch (cfg) { case 0: *state = ROT_IDLE; return; case 1: *state = ROT_RESERVED; return; case 2: *state = ROT_RUNNING; return; case 3: *state = ROT_RUNNING_REMAIN; return; }; } void rot_dump_register(struct rot_dev *rot) { unsigned int tmp, i; rot_dbg("dump rotator registers\n"); for (i = 0; i <= ROTATOR_DST; i += 0x4) { tmp = readl(rot->regs + i); rot_dbg("+0x%x: 0x%x", i, tmp); } }