// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015-2016 MediaTek Inc.
* Author: Houlong Wei <houlong.wei@mediatek.com>
* Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
*/
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include "mtk_mdp_core.h"
#include "mtk_mdp_m2m.h"
#include "mtk_mdp_regs.h"
#include "mtk_vpu.h"
/**
* struct mtk_mdp_pix_limit - image pixel size limits
* @org_w: source pixel width
* @org_h: source pixel height
* @target_rot_dis_w: pixel dst scaled width with the rotator is off
* @target_rot_dis_h: pixel dst scaled height with the rotator is off
* @target_rot_en_w: pixel dst scaled width with the rotator is on
* @target_rot_en_h: pixel dst scaled height with the rotator is on
*/
struct mtk_mdp_pix_limit {
u16 org_w;
u16 org_h;
u16 target_rot_dis_w;
u16 target_rot_dis_h;
u16 target_rot_en_w;
u16 target_rot_en_h;
};
static struct mtk_mdp_pix_align mtk_mdp_size_align = {
.org_w = 16,
.org_h = 16,
.target_w = 2,
.target_h = 2,
};
static const struct mtk_mdp_fmt mtk_mdp_formats[] = {
{
.pixelformat = V4L2_PIX_FMT_MT21C,
.depth = { 8, 4 },
.row_depth = { 8, 8 },
.num_planes = 2,
.num_comp = 2,
.align = &mtk_mdp_size_align,
.flags = MTK_MDP_FMT_FLAG_OUTPUT,
}, {
.pixelformat = V4L2_PIX_FMT_NV12M,
.depth = { 8, 4 },
.row_depth = { 8, 8 },
.num_planes = 2,
.num_comp = 2,
.flags = MTK_MDP_FMT_FLAG_OUTPUT |
MTK_MDP_FMT_FLAG_CAPTURE,
}, {
.pixelformat = V4L2_PIX_FMT_YUV420M,
.depth = { 8, 2, 2 },
.row_depth = { 8, 4, 4 },
.num_planes = 3,
.num_comp = 3,
.flags = MTK_MDP_FMT_FLAG_OUTPUT |
MTK_MDP_FMT_FLAG_CAPTURE,
}, {
.pixelformat = V4L2_PIX_FMT_YVU420,
.depth = { 12 },
.row_depth = { 8 },
.num_planes = 1,
.num_comp = 3,
.flags = MTK_MDP_FMT_FLAG_OUTPUT |
MTK_MDP_FMT_FLAG_CAPTURE,
}
};
static struct mtk_mdp_pix_limit mtk_mdp_size_max = {
.target_rot_dis_w = 4096,
.target_rot_dis_h = 4096,
.target_rot_en_w = 4096,
.target_rot_en_h = 4096,
};
static struct mtk_mdp_pix_limit mtk_mdp_size_min = {
.org_w = 16,
.org_h = 16,
.target_rot_dis_w = 16,
.target_rot_dis_h = 16,
.target_rot_en_w = 16,
.target_rot_en_h = 16,
};
/* align size for normal raster scan pixel format */
static struct mtk_mdp_pix_align mtk_mdp_rs_align = {
.org_w = 2,
.org_h = 2,
.target_w = 2,
.target_h = 2,
};
static struct mtk_mdp_variant mtk_mdp_default_variant = {
.pix_max = &mtk_mdp_size_max,
.pix_min = &mtk_mdp_size_min,
.pix_align = &mtk_mdp_rs_align,
.h_scale_up_max = 32,
.v_scale_up_max = 32,
.h_scale_down_max = 32,
.v_scale_down_max = 128,
};
static const struct mtk_mdp_fmt *mtk_mdp_find_fmt(u32 pixelformat, u32 type)
{
u32 i, flag;
flag = V4L2_TYPE_IS_OUTPUT(type) ? MTK_MDP_FMT_FLAG_OUTPUT :
MTK_MDP_FMT_FLAG_CAPTURE;
for (i = 0; i < ARRAY_SIZE(mtk_mdp_formats); ++i) {
if (!(mtk_mdp_formats[i].flags & flag))
continue;
if (mtk_mdp_formats[i].pixelformat == pixelformat<