brintos

brintos / linux-shallow public Read only

0
0
Text · 7.1 KiB · 08578a1 Raw
255 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * camss-csid-4-7.c4 *5 * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module6 *7 * Copyright (C) 2020 Linaro Ltd.8 */9#include <linux/completion.h>10#include <linux/interrupt.h>11#include <linux/io.h>12#include <linux/kernel.h>13#include <linux/of.h>14 15#include "camss-csid.h"16#include "camss-csid-gen1.h"17#include "camss.h"18 19#define CAMSS_CSID_HW_VERSION		0x020#define CAMSS_CSID_CORE_CTRL_0		0x00421#define CAMSS_CSID_CORE_CTRL_1		0x00822#define CAMSS_CSID_RST_CMD		0x01023#define CAMSS_CSID_CID_LUT_VC_n(n)	(0x014 + 0x4 * (n))24#define CAMSS_CSID_CID_n_CFG(n)		(0x024 + 0x4 * (n))25#define CAMSS_CSID_CID_n_CFG_ISPIF_EN	BIT(0)26#define CAMSS_CSID_CID_n_CFG_RDI_EN	BIT(1)27#define CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT	428#define CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_8		(PLAIN_FORMAT_PLAIN8 << 8)29#define CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_16		(PLAIN_FORMAT_PLAIN16 << 8)30#define CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_LSB	(0 << 9)31#define CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_MSB	(1 << 9)32#define CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP		(0 << 10)33#define CAMSS_CSID_CID_n_CFG_RDI_MODE_PLAIN_PACKING	(1 << 10)34#define CAMSS_CSID_IRQ_CLEAR_CMD	0x06435#define CAMSS_CSID_IRQ_MASK		0x06836#define CAMSS_CSID_IRQ_STATUS		0x06c37#define CAMSS_CSID_TG_CTRL		0x0a838#define CAMSS_CSID_TG_CTRL_DISABLE	0xa0643639#define CAMSS_CSID_TG_CTRL_ENABLE	0xa0643740#define CAMSS_CSID_TG_VC_CFG		0x0ac41#define CAMSS_CSID_TG_VC_CFG_H_BLANKING		0x3ff42#define CAMSS_CSID_TG_VC_CFG_V_BLANKING		0x7f43#define CAMSS_CSID_TG_DT_n_CGG_0(n)	(0x0b4 + 0xc * (n))44#define CAMSS_CSID_TG_DT_n_CGG_1(n)	(0x0b8 + 0xc * (n))45#define CAMSS_CSID_TG_DT_n_CGG_2(n)	(0x0bc + 0xc * (n))46 47static void csid_configure_stream(struct csid_device *csid, u8 enable)48{49	struct csid_testgen_config *tg = &csid->testgen;50	u32 sink_code = csid->fmt[MSM_CSID_PAD_SINK].code;51	u32 src_code = csid->fmt[MSM_CSID_PAD_SRC].code;52	u32 val;53 54	if (enable) {55		struct v4l2_mbus_framefmt *input_format;56		const struct csid_format_info *format;57		u8 vc = 0; /* Virtual Channel 0 */58		u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */59		u8 dt_shift;60 61		if (tg->enabled) {62			/* Config Test Generator */63			u32 num_bytes_per_line, num_lines;64 65			input_format = &csid->fmt[MSM_CSID_PAD_SRC];66			format = csid_get_fmt_entry(csid->res->formats->formats,67						    csid->res->formats->nformats,68						    input_format->code);69			num_bytes_per_line = input_format->width * format->bpp * format->spp / 8;70			num_lines = input_format->height;71 72			/* 31:24 V blank, 23:13 H blank, 3:2 num of active DT */73			/* 1:0 VC */74			val = ((CAMSS_CSID_TG_VC_CFG_V_BLANKING & 0xff) << 24) |75				  ((CAMSS_CSID_TG_VC_CFG_H_BLANKING & 0x7ff) << 13);76			writel_relaxed(val, csid->base + CAMSS_CSID_TG_VC_CFG);77 78			/* 28:16 bytes per lines, 12:0 num of lines */79			val = ((num_bytes_per_line & 0x1fff) << 16) |80				  (num_lines & 0x1fff);81			writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_0(0));82 83			/* 5:0 data type */84			val = format->data_type;85			writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_1(0));86 87			/* 2:0 output test pattern */88			val = tg->mode - 1;89			writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_2(0));90		} else {91			struct csid_phy_config *phy = &csid->phy;92 93			input_format = &csid->fmt[MSM_CSID_PAD_SINK];94			format = csid_get_fmt_entry(csid->res->formats->formats,95						    csid->res->formats->nformats,96						    input_format->code);97 98			val = phy->lane_cnt - 1;99			val |= phy->lane_assign << 4;100 101			writel_relaxed(val, csid->base + CAMSS_CSID_CORE_CTRL_0);102 103			val = phy->csiphy_id << 17;104			val |= 0x9;105 106			writel_relaxed(val, csid->base + CAMSS_CSID_CORE_CTRL_1);107		}108 109		/* Config LUT */110 111		dt_shift = (cid % 4) * 8;112 113		val = readl_relaxed(csid->base + CAMSS_CSID_CID_LUT_VC_n(vc));114		val &= ~(0xff << dt_shift);115		val |= format->data_type << dt_shift;116		writel_relaxed(val, csid->base + CAMSS_CSID_CID_LUT_VC_n(vc));117 118		val = CAMSS_CSID_CID_n_CFG_ISPIF_EN;119		val |= CAMSS_CSID_CID_n_CFG_RDI_EN;120		val |= format->decode_format << CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT;121		val |= CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP;122 123		if ((sink_code == MEDIA_BUS_FMT_SBGGR10_1X10 &&124		     src_code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) ||125		    (sink_code == MEDIA_BUS_FMT_Y10_1X10 &&126		     src_code == MEDIA_BUS_FMT_Y10_2X8_PADHI_LE)) {127			val |= CAMSS_CSID_CID_n_CFG_RDI_MODE_PLAIN_PACKING;128			val |= CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_16;129			val |= CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_LSB;130		}131 132		writel_relaxed(val, csid->base + CAMSS_CSID_CID_n_CFG(cid));133 134		if (tg->enabled) {135			val = CAMSS_CSID_TG_CTRL_ENABLE;136			writel_relaxed(val, csid->base + CAMSS_CSID_TG_CTRL);137		}138	} else {139		if (tg->enabled) {140			val = CAMSS_CSID_TG_CTRL_DISABLE;141			writel_relaxed(val, csid->base + CAMSS_CSID_TG_CTRL);142		}143	}144}145 146static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)147{148	if (val > 0 && val <= csid->testgen.nmodes)149		csid->testgen.mode = val;150 151	return 0;152}153 154static u32 csid_hw_version(struct csid_device *csid)155{156	u32 hw_version = readl_relaxed(csid->base + CAMSS_CSID_HW_VERSION);157 158	dev_dbg(csid->camss->dev, "CSID HW Version = 0x%08x\n", hw_version);159 160	return hw_version;161}162 163/*164 * isr - CSID module interrupt service routine165 * @irq: Interrupt line166 * @dev: CSID device167 *168 * Return IRQ_HANDLED on success169 */170static irqreturn_t csid_isr(int irq, void *dev)171{172	struct csid_device *csid = dev;173	u32 value;174 175	value = readl_relaxed(csid->base + CAMSS_CSID_IRQ_STATUS);176	writel_relaxed(value, csid->base + CAMSS_CSID_IRQ_CLEAR_CMD);177 178	if ((value >> 11) & 0x1)179		complete(&csid->reset_complete);180 181	return IRQ_HANDLED;182}183 184/*185 * csid_reset - Trigger reset on CSID module and wait to complete186 * @csid: CSID device187 *188 * Return 0 on success or a negative error code otherwise189 */190static int csid_reset(struct csid_device *csid)191{192	unsigned long time;193 194	reinit_completion(&csid->reset_complete);195 196	writel_relaxed(0x7fff, csid->base + CAMSS_CSID_RST_CMD);197 198	time = wait_for_completion_timeout(&csid->reset_complete,199					   msecs_to_jiffies(CSID_RESET_TIMEOUT_MS));200	if (!time) {201		dev_err(csid->camss->dev, "CSID reset timeout\n");202		return -EIO;203	}204 205	return 0;206}207 208static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code,209			     unsigned int match_format_idx, u32 match_code)210{211	switch (sink_code) {212	case MEDIA_BUS_FMT_SBGGR10_1X10:213	{214		u32 src_code[] = {215			MEDIA_BUS_FMT_SBGGR10_1X10,216			MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,217		};218 219		return csid_find_code(src_code, ARRAY_SIZE(src_code),220				      match_format_idx, match_code);221	}222	case MEDIA_BUS_FMT_Y10_1X10:223	{224		u32 src_code[] = {225			MEDIA_BUS_FMT_Y10_1X10,226			MEDIA_BUS_FMT_Y10_2X8_PADHI_LE,227		};228 229		return csid_find_code(src_code, ARRAY_SIZE(src_code),230				      match_format_idx, match_code);231	}232	default:233		if (match_format_idx > 0)234			return 0;235 236		return sink_code;237	}238}239 240static void csid_subdev_init(struct csid_device *csid)241{242	csid->testgen.modes = csid_testgen_modes;243	csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN1;244}245 246const struct csid_hw_ops csid_ops_4_7 = {247	.configure_stream = csid_configure_stream,248	.configure_testgen_pattern = csid_configure_testgen_pattern,249	.hw_version = csid_hw_version,250	.isr = csid_isr,251	.reset = csid_reset,252	.src_pad_code = csid_src_pad_code,253	.subdev_init = csid_subdev_init,254};255