// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015 VanguardiaSur - www.vanguardiasur.com.ar
*
* Based on original driver by Krzysztof Ha?asa:
* Copyright (C) 2015 Industrial Research Institute for Automation
* and Measurements PIAP
*/
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
#include <media/videobuf2-dma-contig.h>
#include <media/videobuf2-dma-sg.h>
#include <media/videobuf2-vmalloc.h>
#include "tw686x.h"
#include "tw686x-regs.h"
#define TW686X_INPUTS_PER_CH 4
#define TW686X_VIDEO_WIDTH 720
#define TW686X_VIDEO_HEIGHT(id) ((id & V4L2_STD_525_60) ? 480 : 576)
#define TW686X_MAX_FPS(id) ((id & V4L2_STD_525_60) ? 30 : 25)
#define TW686X_MAX_SG_ENTRY_SIZE 4096
#define TW686X_MAX_SG_DESC_COUNT 256 /* PAL 720x576 needs 203 4-KB pages */
#define TW686X_SG_TABLE_SIZE (TW686X_MAX_SG_DESC_COUNT * sizeof(struct tw686x_sg_desc))
static const struct tw686x_format formats[] = {
{
.fourcc = V4L2_PIX_FMT_UYVY,
.mode = 0,
.depth = 16,
}, {
.fourcc = V4L2_PIX_FMT_RGB565,
.mode = 5,
.depth = 16,
}, {
.fourcc = V4L2_PIX_FMT_YUYV,
.mode = 6,
.depth = 16,
}
};
static void tw686x_buf_done(struct tw686x_video_channel *vc,
unsigned int pb)
{
struct tw686x_dma_desc *desc = &vc->dma_descs[pb];
struct tw686x_dev *dev = vc->dev;
struct vb2_v4l2_buffer *vb;
struct vb2_buffer *vb2_buf;
if (vc->curr_bufs[pb]) {
vb = &vc->curr_bufs[pb]->vb;
vb->field = dev->dma_ops->field;
vb->sequence = vc->sequence++;
vb2_buf = &vb->vb2_buf;
if (dev->dma_mode == TW686X_DMA_MODE_MEMCPY)
memcpy(vb2_plane_vaddr(vb2_buf, 0), desc->virt,
desc->size);
vb2_buf->timestamp = ktime_get_ns();
vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE);
}
vc->pb = !pb;
}
/*
* We can call this even when alloc_dma failed for the given channel
*/
static void tw686x_memcpy_dma_free(struct tw686x_video_channel *vc,
unsigned int pb)
{
struct tw686x_dma_desc *desc = &vc->dma_descs[pb];