// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2012 Texas Instruments Inc
*
* 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 version 2.
*
* 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.
*
* Contributors:
* Manjunath Hadli <manjunath.hadli@ti.com>
* Prabhakar Lad <prabhakar.lad@ti.com>
*/
#include "dm365_ipipeif.h"
#include "vpfe_mc_capture.h"
static const unsigned int ipipeif_input_fmts[] = {
MEDIA_BUS_FMT_UYVY8_2X8,
MEDIA_BUS_FMT_SGRBG12_1X12,
MEDIA_BUS_FMT_Y8_1X8,
MEDIA_BUS_FMT_UV8_1X8,
MEDIA_BUS_FMT_YDYUYDYV8_1X16,
MEDIA_BUS_FMT_SBGGR8_1X8,
};
static const unsigned int ipipeif_output_fmts[] = {
MEDIA_BUS_FMT_UYVY8_2X8,
MEDIA_BUS_FMT_SGRBG12_1X12,
MEDIA_BUS_FMT_Y8_1X8,
MEDIA_BUS_FMT_UV8_1X8,
MEDIA_BUS_FMT_YDYUYDYV8_1X16,
MEDIA_BUS_FMT_SBGGR8_1X8,
MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8,
};
static int
ipipeif_get_pack_mode(u32 in_pix_fmt)
{
switch (in_pix_fmt) {
case MEDIA_BUS_FMT_SBGGR8_1X8:
case MEDIA_BUS_FMT_Y8_1X8:
case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
case MEDIA_BUS_FMT_UV8_1X8:
return IPIPEIF_5_1_PACK_8_BIT;
case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8:
return IPIPEIF_5_1_PACK_8_BIT_A_LAW;
case MEDIA_BUS_FMT_SGRBG12_1X12:
return IPIPEIF_5_1_PACK_16_BIT;
case MEDIA_BUS_FMT_SBGGR12_1X12:
return IPIPEIF_5_1_PACK_12_BIT;
default:
return IPIPEIF_5_1_PACK_16_BIT;
}
}
static inline u32 ipipeif_read(void __iomem *addr, u32 offset)
{
return readl(addr + offset);
}
static inline void ipipeif_write(u32 val, void __iomem *addr, u32 offset)
{
writel(val, addr + offset);
}
static void ipipeif_config_dpc(void __iomem *addr, struct ipipeif_dpc *dpc)
{
u32 val = 0;
if (dpc->en) {
val = (dpc->en & 1) << IPIPEIF_DPC2_EN_SHIFT;
val |= dpc->thr & IPIPEIF_DPC2_THR_MASK;
}
ipipeif_write(val, addr, IPIPEIF_DPC2);
}
#define IPIPEIF_MODE_CONTINUOUS 0
#define IPIPEIF_MODE_ONE_SHOT 1
static int get_oneshot_mode(enum ipipeif_input_entity input)
{
if (input == IPIPEIF_INPUT_MEMORY)
return IPIPEIF_MODE_ONE_SHOT;
if (input == IPIPEIF_INPUT_ISIF)
return IPIPEIF_MODE_CONTINUOUS;
return -EINVAL;
}
static int
ipipeif_get_cfg_src1(struct vpfe_ipipeif_device *ipipeif)
{
struct v4l2_mbus_framefmt *informat;
informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
if (ipipeif->input == IPIPEIF_INPUT_MEMORY &&
(informat->code == MEDIA_BUS_FMT_Y8_1X8 ||
informat->code == MEDIA_BUS_FMT_UV8_1X8))
return IPIPEIF_CCDC;
return IPIPEIF_SRC1_PARALLEL_PORT;
}
static int
ipipeif_get_data_shift(struct vpfe_ipipeif_device *ipipeif)
{
struct v4l2_mbus_framefmt *informat;
informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
switch (informat->code) {
case MEDIA_BUS_FMT_SGRBG12_1X12:
return IPIPEIF_5_1_BITS11_0;
case MEDIA_BUS_FMT_Y8_1X8:
case MEDIA_BUS_FMT_UV8_1X8:
return IPIPEIF_5_1_BITS11_0;
default:
return IPIPEIF_5_1_BITS7_0;
}
}
static enum ipipeif_input_source
ipipeif_get_source(struct vpfe_ipipeif_device *ipipeif)
{
struct v4l2_mbus_framefmt *informat;
informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
if (ipipeif->input == IPIPEIF_INPUT_ISIF)
return IPIPEIF_CCDC;
if (informat->code == MEDIA_BUS_FMT_UYVY8_2X8)
return IPIPEIF_SDRAM_YUV;
return IPIPEIF_SDRAM_RAW;
}
void vpfe_ipipeif_ss_buffer_isr(struct vpfe_ipipeif_device *ipipeif)
{
struct vpfe_video_device *video_in = &ipipeif->video_in;
if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
return;
spin_lock(&video_in->dma_queue_lock);
vpfe_video_process_buffer_complete(video_in);
video_in->state = VPFE_VIDEO_BUFFER_NOT_QUEUED;
vpfe_video_schedule_next_buffer(video_in