Commit e7b59e1d authored by Vikram Sharma's avatar Vikram Sharma Committed by Mauro Carvalho Chehab
Browse files

media: qcom: camss: Add support for VFE 690



Add support for VFE 690 found on lemans(SA8775P). This is
different from vfe 780 w.r.t few register offsets. It
supports two full and five lite VFE.

Co-developed-by: default avatarSuresh Vankadara <quic_svankada@quicinc.com>
Signed-off-by: default avatarSuresh Vankadara <quic_svankada@quicinc.com>
Co-developed-by: default avatarWenmeng Liu <quic_wenmliu@quicinc.com>
Signed-off-by: default avatarWenmeng Liu <quic_wenmliu@quicinc.com>
Signed-off-by: default avatarVikram Sharma <quic_vikramsa@quicinc.com>
Signed-off-by: default avatarBryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: default avatarBryan O'Donoghue <bod@kernel.org>
Signed-off-by: default avatarHans Verkuil <hverkuil+cisco@kernel.org>
parent ed03e99d
Loading
Loading
Loading
Loading
+50 −17
Original line number Diff line number Diff line
@@ -12,13 +12,43 @@
#include "camss.h"
#include "camss-vfe.h"

#define BUS_REG_BASE			(vfe_is_lite(vfe) ? 0x200 : 0xC00)
#define IS_VFE_690(vfe) \
	    (vfe->camss->res->version == CAMSS_8775P)

#define BUS_REG_BASE_690 \
	    (vfe_is_lite(vfe) ? 0x480 : 0x400)
#define BUS_REG_BASE_780 \
	    (vfe_is_lite(vfe) ? 0x200 : 0xC00)
#define BUS_REG_BASE \
	    (IS_VFE_690(vfe) ? BUS_REG_BASE_690 : BUS_REG_BASE_780)

#define VFE_TOP_CORE_CFG (0x24)
#define VFE_DISABLE_DSCALING_DS4  BIT(21)
#define VFE_DISABLE_DSCALING_DS16 BIT(22)

#define VFE_BUS_WM_TEST_BUS_CTRL_690 (BUS_REG_BASE + 0xFC)
#define VFE_BUS_WM_TEST_BUS_CTRL_780 (BUS_REG_BASE + 0xDC)
#define VFE_BUS_WM_TEST_BUS_CTRL \
	    (IS_VFE_690(vfe) ? VFE_BUS_WM_TEST_BUS_CTRL_690 \
	     : VFE_BUS_WM_TEST_BUS_CTRL_780)
/*
 * Bus client mapping:
 *
 * Full VFE:
 * VFE_690: 16 = RDI0, 17 = RDI1, 18 = RDI2
 * VFE_780: 23 = RDI0, 24 = RDI1, 25 = RDI2
 *
 * VFE LITE:
 * VFE_690 : 0 = RDI0, 1 = RDI1, 2 = RDI2, 3 = RDI3, 4 = RDI4, 5 = RDI5
 * VFE_780 : 0 = RDI0, 1 = RDI1, 2 = RDI2, 3 = RDI3, 4 = RDI4
 */
#define RDI_WM_690(n)	((vfe_is_lite(vfe) ? 0x0 : 0x10) + (n))
#define RDI_WM_780(n)	((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n))
#define RDI_WM(n)	(IS_VFE_690(vfe) ? RDI_WM_690(n) : RDI_WM_780(n))

#define VFE_BUS_WM_CGC_OVERRIDE		(BUS_REG_BASE + 0x08)
#define		WM_CGC_OVERRIDE_ALL		(0x7FFFFFF)

#define VFE_BUS_WM_TEST_BUS_CTRL	(BUS_REG_BASE + 0xDC)

#define VFE_BUS_WM_CFG(n)		(BUS_REG_BASE + 0x200 + (n) * 0x100)
#define		WM_CFG_EN			BIT(0)
#define		WM_VIR_FRM_EN			BIT(1)
@@ -39,17 +69,6 @@
#define VFE_BUS_WM_MMU_PREFETCH_CFG(n)		(BUS_REG_BASE + 0x260 + (n) * 0x100)
#define VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(n)	(BUS_REG_BASE + 0x264 + (n) * 0x100)

/*
 * Bus client mapping:
 *
 * Full VFE:
 * 23 = RDI0, 24 = RDI1, 25 = RDI2
 *
 * VFE LITE:
 * 0 = RDI0, 1 = RDI1, 2 = RDI3, 4 = RDI4
 */
#define RDI_WM(n)			((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n))

static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line)
{
	struct v4l2_pix_format_mplane *pix =
@@ -62,14 +81,24 @@ static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line)

	writel(0x0, vfe->base + VFE_BUS_WM_TEST_BUS_CTRL);

	if (IS_VFE_690(vfe))
		writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height,
		       vfe->base + VFE_BUS_WM_FRAME_INCR(wm));
	else
		writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height >> 8,
		       vfe->base + VFE_BUS_WM_FRAME_INCR(wm));

	writel((WM_IMAGE_CFG_0_DEFAULT_WIDTH & 0xFFFF),
	       vfe->base + VFE_BUS_WM_IMAGE_CFG_0(wm));
	writel(WM_IMAGE_CFG_2_DEFAULT_STRIDE,
	       vfe->base + VFE_BUS_WM_IMAGE_CFG_2(wm));
	writel(0, vfe->base + VFE_BUS_WM_PACKER_CFG(wm));

	/* TOP CORE CFG */
	if (IS_VFE_690(vfe))
		writel(VFE_DISABLE_DSCALING_DS4 | VFE_DISABLE_DSCALING_DS16,
			vfe->base + VFE_TOP_CORE_CFG);

	/* no dropped frames, one irq per frame */
	writel(0, vfe->base + VFE_BUS_WM_FRAMEDROP_PERIOD(wm));
	writel(1, vfe->base + VFE_BUS_WM_FRAMEDROP_PATTERN(wm));
@@ -92,7 +121,11 @@ static void vfe_wm_update(struct vfe_device *vfe, u8 wm, u32 addr,
			  struct vfe_line *line)
{
	wm = RDI_WM(wm);
	writel((addr >> 8) & 0xFFFFFFFF, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm));

	if (IS_VFE_690(vfe))
		writel(addr, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm));
	else
		writel((addr >> 8), vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm));

	dev_dbg(vfe->camss->dev, "wm:%d, image buf addr:0x%x\n",
		wm, addr);
+22 −3
Original line number Diff line number Diff line
@@ -347,6 +347,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
	case CAMSS_8280XP:
	case CAMSS_845:
	case CAMSS_8550:
	case CAMSS_8775P:
	case CAMSS_X1E80100:
		switch (sink_code) {
		case MEDIA_BUS_FMT_YUYV8_1X16:
@@ -911,7 +912,24 @@ static int vfe_match_clock_names(struct vfe_device *vfe,

	return (!strcmp(clock->name, vfe_name) ||
		!strcmp(clock->name, vfe_lite_name) ||
		!strcmp(clock->name, "vfe_lite"));
		!strcmp(clock->name, "vfe_lite") ||
		!strcmp(clock->name, "camnoc_axi"));
}

/*
 * vfe_check_clock_levels - Calculate and set clock rates on VFE module
 * @clock: clocks data
 *
 * Return false if there is no non-zero clock level and true otherwise.
 */
static bool vfe_check_clock_levels(struct camss_clock *clock)
{
	int i;

	for (i = 0; i < clock->nfreqs; i++)
		if (clock->freq[i])
			return true;
	return false;
}

/*
@@ -937,7 +955,7 @@ static int vfe_set_clock_rates(struct vfe_device *vfe)
	for (i = 0; i < vfe->nclocks; i++) {
		struct camss_clock *clock = &vfe->clock[i];

		if (vfe_match_clock_names(vfe, clock)) {
		if (vfe_match_clock_names(vfe, clock) && vfe_check_clock_levels(clock)) {
			u64 min_rate = 0;
			long rate;

@@ -1018,7 +1036,7 @@ static int vfe_check_clock_rates(struct vfe_device *vfe)
	for (i = 0; i < vfe->nclocks; i++) {
		struct camss_clock *clock = &vfe->clock[i];

		if (vfe_match_clock_names(vfe, clock)) {
		if (vfe_match_clock_names(vfe, clock) && vfe_check_clock_levels(clock)) {
			u64 min_rate = 0;
			unsigned long rate;

@@ -1976,6 +1994,7 @@ static int vfe_bpl_align(struct vfe_device *vfe)
	case CAMSS_8280XP:
	case CAMSS_845:
	case CAMSS_8550:
	case CAMSS_8775P:
	case CAMSS_X1E80100:
		ret = 16;
		break;
+174 −0
Original line number Diff line number Diff line
@@ -2821,6 +2821,180 @@ static const struct camss_subdev_resources csid_res_8775p[] = {
	},
};

static const struct camss_subdev_resources vfe_res_8775p[] = {
	/* VFE0 */
	{
		.regulators = {},
		.clock = { "cpas_vfe0", "vfe0", "vfe0_fast_ahb",
			   "cpas_ahb", "gcc_axi_hf",
			   "cpas_fast_ahb_clk",
			   "camnoc_axi"},
		.clock_rate = {
			{ 0 },
			{ 480000000 },
			{ 300000000, 400000000 },
			{ 300000000, 400000000 },
			{ 0 },
			{ 300000000, 400000000 },
			{ 400000000 },
		},
		.reg = { "vfe0" },
		.interrupt = { "vfe0" },
		.vfe = {
			.line_num = 3,
			.is_lite = false,
			.has_pd = false,
			.pd_name = NULL,
			.hw_ops = &vfe_ops_gen3,
			.formats_rdi = &vfe_formats_rdi_845,
			.formats_pix = &vfe_formats_pix_845
		}
	},
	/* VFE1 */
	{
		.regulators = {},
		.clock = { "cpas_vfe1", "vfe1", "vfe1_fast_ahb",
			   "cpas_ahb", "gcc_axi_hf",
			   "cpas_fast_ahb_clk",
			   "camnoc_axi"},
		.clock_rate = {
			{ 0 },
			{ 480000000 },
			{ 300000000, 400000000 },
			{ 300000000, 400000000 },
			{ 0 },
			{ 300000000, 400000000 },
			{ 400000000 },
		},
		.reg = { "vfe1" },
		.interrupt = { "vfe1" },
		.vfe = {
			.line_num = 3,
			.is_lite = false,
			.has_pd = false,
			.pd_name = NULL,
			.hw_ops = &vfe_ops_gen3,
			.formats_rdi = &vfe_formats_rdi_845,
			.formats_pix = &vfe_formats_pix_845
		}
	},
	/* VFE2 (lite) */
	{
		.regulators = {},
		.clock = { "cpas_vfe_lite", "vfe_lite_ahb",
			   "vfe_lite_csid", "vfe_lite_cphy_rx",
			   "vfe_lite"},
		.clock_rate = {
			{ 0, 0, 0, 0  },
			{ 300000000, 400000000, 400000000, 400000000 },
			{ 400000000, 400000000, 400000000, 400000000 },
			{ 400000000, 400000000, 400000000, 400000000 },
			{ 480000000, 600000000, 600000000, 600000000 },
		},
		.reg = { "vfe_lite0" },
		.interrupt = { "vfe_lite0" },
		.vfe = {
			.line_num = 4,
			.is_lite = true,
			.hw_ops = &vfe_ops_gen3,
			.formats_rdi = &vfe_formats_rdi_845,
			.formats_pix = &vfe_formats_pix_845
		}
	},
	/* VFE3 (lite) */
	{
		.regulators = {},
		.clock = { "cpas_vfe_lite", "vfe_lite_ahb",
			   "vfe_lite_csid", "vfe_lite_cphy_rx",
			   "vfe_lite"},
		.clock_rate = {
			{ 0, 0, 0, 0  },
			{ 300000000, 400000000, 400000000, 400000000 },
			{ 400000000, 400000000, 400000000, 400000000 },
			{ 400000000, 400000000, 400000000, 400000000 },
			{ 480000000, 600000000, 600000000, 600000000 },
		},
		.reg = { "vfe_lite1" },
		.interrupt = { "vfe_lite1" },
		.vfe = {
			.line_num = 4,
			.is_lite = true,
			.hw_ops = &vfe_ops_gen3,
			.formats_rdi = &vfe_formats_rdi_845,
			.formats_pix = &vfe_formats_pix_845
		}
	},
	/* VFE4 (lite) */
	{
		.regulators = {},
		.clock = { "cpas_vfe_lite", "vfe_lite_ahb",
			   "vfe_lite_csid", "vfe_lite_cphy_rx",
			   "vfe_lite"},
		.clock_rate = {
			{ 0, 0, 0, 0  },
			{ 300000000, 400000000, 400000000, 400000000 },
			{ 400000000, 400000000, 400000000, 400000000 },
			{ 400000000, 400000000, 400000000, 400000000 },
			{ 480000000, 600000000, 600000000, 600000000 },
		},
		.reg = { "vfe_lite2" },
		.interrupt = { "vfe_lite2" },
		.vfe = {
			.line_num = 4,
			.is_lite = true,
			.hw_ops = &vfe_ops_gen3,
			.formats_rdi = &vfe_formats_rdi_845,
			.formats_pix = &vfe_formats_pix_845
		}
	},
	/* VFE5 (lite) */
	{
		.regulators = {},
		.clock = { "cpas_vfe_lite", "vfe_lite_ahb",
			   "vfe_lite_csid", "vfe_lite_cphy_rx",
			   "vfe_lite"},
		.clock_rate = {
			{ 0, 0, 0, 0  },
			{ 300000000, 400000000, 400000000, 400000000 },
			{ 400000000, 400000000, 400000000, 400000000 },
			{ 400000000, 400000000, 400000000, 400000000 },
			{ 480000000, 600000000, 600000000, 600000000 },
		},
		.reg = { "vfe_lite3" },
		.interrupt = { "vfe_lite3" },
		.vfe = {
			.line_num = 4,
			.is_lite = true,
			.hw_ops = &vfe_ops_gen3,
			.formats_rdi = &vfe_formats_rdi_845,
			.formats_pix = &vfe_formats_pix_845
		}
	},
	/* VFE6 (lite) */
	{
		.regulators = {},
		.clock = { "cpas_vfe_lite", "vfe_lite_ahb",
			   "vfe_lite_csid", "vfe_lite_cphy_rx",
			   "vfe_lite"},
		.clock_rate = {
			{ 0, 0, 0, 0  },
			{ 300000000, 400000000, 400000000, 400000000 },
			{ 400000000, 400000000, 400000000, 400000000 },
			{ 400000000, 400000000, 400000000, 400000000 },
			{ 480000000, 600000000, 600000000, 600000000 },
		},
		.reg = { "vfe_lite4" },
		.interrupt = { "vfe_lite4" },
		.vfe = {
			.line_num = 4,
			.is_lite = true,
			.hw_ops = &vfe_ops_gen3,
			.formats_rdi = &vfe_formats_rdi_845,
			.formats_pix = &vfe_formats_pix_845
		}
	},
};

static const struct resources_icc icc_res_sa8775p[] = {
	{
		.name = "ahb",