/*
* Driver for Renesas R-Car VIN
*
* Copyright (C) 2016 Renesas Electronics Corp.
* Copyright (C) 2011-2013 Renesas Solutions Corp.
* Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
* Copyright (C) 2008 Magnus Damm
*
* Based on the soc-camera rcar_vin driver
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <media/videobuf2-dma-contig.h>
#include "rcar-vin.h"
/* -----------------------------------------------------------------------------
* HW Functions
*/
/* Register offsets for R-Car VIN */
#define VNMC_REG 0x00 /* Video n Main Control Register */
#define VNMS_REG 0x04 /* Video n Module Status Register */
#define VNFC_REG 0x08 /* Video n Frame Capture Register */
#define VNSLPRC_REG 0x0C /* Video n Start Line Pre-Clip Register */
#define VNELPRC_REG 0x10 /* Video n End Line Pre-Clip Register */
#define VNSPPRC_REG 0x14 /* Video n Start Pixel Pre-Clip Register */
#define VNEPPRC_REG 0x18 /* Video n End Pixel Pre-Clip Register */
#define VNSLPOC_REG 0x1C /* Video n Start Line Post-Clip Register */
#define VNELPOC_REG 0x20 /* Video n End Line Post-Clip Register */
#define VNSPPOC_REG 0x24 /* Video n Start Pixel Post-Clip Register */
#define VNEPPOC_REG 0x28 /* Video n End Pixel Post-Clip Register */
#define VNIS_REG 0x2C /* Video n Image Stride Register */
#define VNMB_REG(m) (0x30 + ((m) << 2)) /* Video n Memory Base m Register */
#define VNIE_REG 0x40 /* Video n Interrupt Enable Register */
#define VNINTS_REG 0x44 /* Video n Interrupt Status Register */
#define VNSI_REG 0x48 /* Video n Scanline Interrupt Register */
#define VNMTC_REG 0x4C /* Video n Memory Transfer Control Register */
#define VNYS_REG 0x50 /* Video n Y Scale Register */
#define VNXS_REG 0x54 /* Video n X Scale Register */
#define VNDMR_REG 0x58 /* Video n Data Mode Register */
#define VNDMR2_REG 0x5C /* Video n Data Mode Register 2 */
#define VNUVAOF_REG 0x60 /* Video n UV Address Offset Register */
#define VNC1A_REG 0x80 /* Video n Coefficient Set C1A Register */
#define VNC1B_REG 0x84 /* Video n Coefficient Set C1B Register */
#define VNC1C_REG 0x88 /* Video n Coefficient Set C1C Register */
#define VNC2A_REG 0x90 /* Video n Coefficient Set C2A Register */
#define VNC2B_REG 0x94 /* Video n Coefficient Set C2B Register */
#define VNC2C_REG 0x98 /* Video n Coefficient Set C2C Register */
#define VNC3A_REG 0xA0 /* Video n Coefficient Set C3A Register */
#define VNC3B_REG 0xA4 /* Video n Coefficient Set C3B Register */
#define VNC3C_REG 0xA8 /* Video n Coefficient Set C3C Register */
#define VNC4A_REG 0xB0 /* Video n Coefficient Set C4A Register */
#define VNC4B_REG 0xB4 /* Video n Coefficient Set C4B Register */
#define VNC4C_REG 0xB8 /* Video n Coefficient Set C4C Register */
#define VNC5A_REG 0xC0 /* Video n Coefficient Set C5A Register */
#define VNC5B_REG 0xC4 /* Video n Coefficient Set C5B Register */
#define VNC5C_REG 0xC8 /* Video n Coefficient Set C5C Register */
#define VNC6A_REG 0xD0 /* Video n Coefficient Set C6A Register */
#define VNC6B_REG 0xD4 /* Video n Coefficient Set C6B Register */
#define VNC6C_REG 0xD8 /* Video n Coefficient Set C6C Register */
#define VNC7A_REG 0xE0 /* Video n Coefficient Set C7A Register */
#define VNC7B_REG 0xE4 /* Video n Coefficient Set C7B Register */
#define VNC7C_REG 0xE8 /* Video n Coefficient Set C7C Register */
#define VNC8A_REG 0xF0 /* Video n Coefficient Set C8A Register */
#define VNC8B_REG 0xF4 /* Video n Coefficient Set C8B Register */
#define VNC8C_REG 0xF8 /* Video n Coefficient Set C8C Register */
/* Register bit fields for R-Car VIN */
/* Video n Main Control Register bits */
#define VNMC_FOC (1 << 21)
#define VNMC_YCAL (1 << 19)
#define VNMC_INF_YUV8_BT656 (0 << 16)
#define VNMC_INF_YUV8_BT601 (1 << 16)
#define VNMC_INF_YUV10_BT656 (2 << 16)
#define VNMC_INF_YUV10_BT601 (3 << 16)
#define VNMC_INF_YUV16 (5 << 16)
#define VNMC_INF_RGB888 (6 << 16)
#define VNMC_VUP (1 << 10)
#define VNMC_IM_ODD (0 << 3)
#define VNMC_IM_ODD_EVEN (1 << 3)
#define VNMC_IM_EVEN (2 << 3)
#define VNMC_IM_FULL (3 << 3)
#define VNMC_BPS (1 << 1)
#define VNMC_ME (1 << 0)
/* Video n Module Status Register bits */
#define VNMS_FBS_MASK (3 << 3)
#define VNMS_FBS_SHIFT 3
#define VNMS_AV (1 << 1)
#define VNMS_CA (1 << 0)
/* Video n Frame Capture Register bits */
#define VNFC_C_FRAME (1 << 1)
#define VNFC_S_FRAME (1 << 0)
/* Video n Interrupt Enable Register bits */
#define VNIE_FIE (1 << 4)
#define VNIE_EFE (1 << 1)
/* Video n Data Mode Register bits */
#define VNDMR_EXRGB (1 << 8)
#define VNDMR_BPSM (1 << 4)
#define VNDMR_DTMD_YCSEP (1 << 1)
#define VNDMR_DTMD_ARGB1555 (1 << 0)
/* Video n Data Mode Register 2 bits */
#define VNDMR2_VPS (1 << 30)
#define VNDMR2_HPS (1 << 29)
#define VNDMR2_FTEV (1 << 17)
#define VNDMR2_VLV(n) ((n & 0xf) << 12)
static void rvin_write(struct rvin_dev *vin, u32 value, u32 offset)
{
iowrite32(value, vin->base + offset);
}
static u32 rvin_read(struct rvin_dev *vin, u32 offset)
{
return ioread32(vin->base + offset);
}
static int rvin_setup(struct rvin_dev *vin)
{
u32 vnmc, dmr, dmr2, interrupts;
bool progressive = false, output_is_yuv = false, input_is_yuv = false;
switch (vin->format.field) {
case V4L2_FIELD_TOP:
vnmc = VNMC_IM_ODD;
break;
case V4L2_FIELD_BOTTOM:
vnmc = VNMC_IM_EVEN;
break;
case V4L2_FIELD_INTERLACED:
case V4L2_FIELD_INTERLACED_TB:
vnmc = VNMC_IM_FULL;
break;
case V4L2_FIELD_INTERLACED_BT:
vnmc = VNMC_IM_FULL | VNMC_FOC;
break;
case V4L2_FIELD_NONE:
if (vin->continuous) {
vnmc = VNMC_IM_ODD_EVEN;
progressive = true;
} else {
vnmc = VNMC_IM_ODD;
}