* Applied "ASoC: fsl_sai: Add support for SAI new version" to the asoc tree
From: Mark Brown @ 2019-08-07 13:30 UTC (permalink / raw)
To: Daniel Baluta
Cc: devicetree, alsa-devel, timur, robh, Shengjiu Wang, angus,
linux-kernel, tiwai, Nicolin Chen, Mark Brown, linux-imx, kernel,
Mihai Serban, festevam, mihai.serban, l.stach
In-Reply-To: <20190806151214.6783-4-daniel.baluta@nxp.com>
The patch
ASoC: fsl_sai: Add support for SAI new version
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.4
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 4f7a0728b5305e2d865f543fbcffd617e03c7674 Mon Sep 17 00:00:00 2001
From: Daniel Baluta <daniel.baluta@nxp.com>
Date: Tue, 6 Aug 2019 18:12:12 +0300
Subject: [PATCH] ASoC: fsl_sai: Add support for SAI new version
New IP version introduces Version ID and Parameter registers
and optionally added Timestamp feature.
VERID and PARAM registers are placed at the top of registers
address space and some registers are shifted according to
the following table:
Tx/Rx data registers and Tx/Rx FIFO registers keep their
addresses, all other registers are shifted by 8.
SAI Memory map is described in chapter 13.10.4.1.1 I2S Memory map
of the Reference Manual [1].
In order to make as less changes as possible we attach an offset
to each register offset to each changed register definition. The
offset is read from each board private data.
[1]https://cache.nxp.com/secured/assets/documents/en/reference-manual/IMX8MDQLQRM.pdf?__gda__=1563728701_38bea7f0f726472cc675cb141b91bec7&fileExt=.pdf
Signed-off-by: Mihai Serban <mihai.serban@nxp.com>
[initial coding in the NXP internal tree]
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
[bugfixing and cleanups]
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
[adapted to linux-next]
Acked-by: Nicolin Chen <nicoleotsuka@gmail.com>
Link: https://lore.kernel.org/r/20190806151214.6783-4-daniel.baluta@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/fsl/fsl_sai.c | 228 ++++++++++++++++++++++++----------------
sound/soc/fsl/fsl_sai.h | 41 ++++----
2 files changed, 156 insertions(+), 113 deletions(-)
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index f2698c94c9fe..0c5452927c04 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -40,6 +40,7 @@ static const struct snd_pcm_hw_constraint_list fsl_sai_rate_constraints = {
static irqreturn_t fsl_sai_isr(int irq, void *devid)
{
struct fsl_sai *sai = (struct fsl_sai *)devid;
+ unsigned int ofs = sai->soc_data->reg_offset;
struct device *dev = &sai->pdev->dev;
u32 flags, xcsr, mask;
bool irq_none = true;
@@ -52,7 +53,7 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
mask = (FSL_SAI_FLAGS >> FSL_SAI_CSR_xIE_SHIFT) << FSL_SAI_CSR_xF_SHIFT;
/* Tx IRQ */
- regmap_read(sai->regmap, FSL_SAI_TCSR, &xcsr);
+ regmap_read(sai->regmap, FSL_SAI_TCSR(ofs), &xcsr);
flags = xcsr & mask;
if (flags)
@@ -82,11 +83,11 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
xcsr &= ~FSL_SAI_CSR_xF_MASK;
if (flags)
- regmap_write(sai->regmap, FSL_SAI_TCSR, flags | xcsr);
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), flags | xcsr);
irq_rx:
/* Rx IRQ */
- regmap_read(sai->regmap, FSL_SAI_RCSR, &xcsr);
+ regmap_read(sai->regmap, FSL_SAI_RCSR(ofs), &xcsr);
flags = xcsr & mask;
if (flags)
@@ -116,7 +117,7 @@ static irqreturn_t fsl_sai_isr(int irq, void *devid)
xcsr &= ~FSL_SAI_CSR_xF_MASK;
if (flags)
- regmap_write(sai->regmap, FSL_SAI_RCSR, flags | xcsr);
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), flags | xcsr);
out:
if (irq_none)
@@ -140,6 +141,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int fsl_dir)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned int ofs = sai->soc_data->reg_offset;
bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
u32 val_cr2 = 0;
@@ -160,7 +162,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
return -EINVAL;
}
- regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
FSL_SAI_CR2_MSEL_MASK, val_cr2);
return 0;
@@ -193,6 +195,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
unsigned int fmt, int fsl_dir)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned int ofs = sai->soc_data->reg_offset;
bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
u32 val_cr2 = 0, val_cr4 = 0;
@@ -287,9 +290,9 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
return -EINVAL;
}
- regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2);
- regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE |
FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4);
@@ -316,6 +319,7 @@ static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
+ unsigned int ofs = sai->soc_data->reg_offset;
unsigned long clk_rate;
u32 savediv = 0, ratio, savesub = freq;
u32 id;
@@ -378,17 +382,17 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
*/
if ((sai->synchronous[TX] && !sai->synchronous[RX]) ||
(!tx && !sai->synchronous[RX])) {
- regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs),
FSL_SAI_CR2_MSEL_MASK,
FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
- regmap_update_bits(sai->regmap, FSL_SAI_RCR2,
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs),
FSL_SAI_CR2_DIV_MASK, savediv - 1);
} else if ((sai->synchronous[RX] && !sai->synchronous[TX]) ||
(tx && !sai->synchronous[TX])) {
- regmap_update_bits(sai->regmap, FSL_SAI_TCR2,
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs),
FSL_SAI_CR2_MSEL_MASK,
FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
- regmap_update_bits(sai->regmap, FSL_SAI_TCR2,
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs),
FSL_SAI_CR2_DIV_MASK, savediv - 1);
}
@@ -403,6 +407,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned int ofs = sai->soc_data->reg_offset;
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
unsigned int channels = params_channels(params);
u32 word_width = params_width(params);
@@ -455,19 +460,19 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
if (!sai->is_slave_mode) {
if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) {
- regmap_update_bits(sai->regmap, FSL_SAI_TCR4,
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR4(ofs),
FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
val_cr4);
- regmap_update_bits(sai->regmap, FSL_SAI_TCR5,
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR5(ofs),
FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
FSL_SAI_CR5_FBT_MASK, val_cr5);
regmap_write(sai->regmap, FSL_SAI_TMR,
~0UL - ((1 << channels) - 1));
} else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) {
- regmap_update_bits(sai->regmap, FSL_SAI_RCR4,
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR4(ofs),
FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
val_cr4);
- regmap_update_bits(sai->regmap, FSL_SAI_RCR5,
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR5(ofs),
FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
FSL_SAI_CR5_FBT_MASK, val_cr5);
regmap_write(sai->regmap, FSL_SAI_RMR,
@@ -475,10 +480,10 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
}
}
- regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
val_cr4);
- regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx),
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx, ofs),
FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
FSL_SAI_CR5_FBT_MASK, val_cr5);
regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << channels) - 1));
@@ -506,6 +511,8 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned int ofs = sai->soc_data->reg_offset;
+
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
u32 xcsr, count = 100;
@@ -514,9 +521,9 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
* Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx.
* Tx sync with Rx clocks: Clear SYNC for Rx, set it for Tx.
*/
- regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC,
- sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0);
- regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC,
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), FSL_SAI_CR2_SYNC,
+ sai->synchronous[TX] ? FSL_SAI_CR2_SYNC : 0);
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), FSL_SAI_CR2_SYNC,
sai->synchronous[RX] ? FSL_SAI_CR2_SYNC : 0);
/*
@@ -527,43 +534,44 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
- regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
- regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
FSL_SAI_CSR_FRDE, 0);
- regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
FSL_SAI_CSR_xIE_MASK, 0);
/* Check if the opposite FRDE is also disabled */
- regmap_read(sai->regmap, FSL_SAI_xCSR(!tx), &xcsr);
+ regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr);
if (!(xcsr & FSL_SAI_CSR_FRDE)) {
/* Disable both directions and reset their FIFOs */
- regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
FSL_SAI_CSR_TERE, 0);
- regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
FSL_SAI_CSR_TERE, 0);
/* TERE will remain set till the end of current frame */
do {
udelay(10);
- regmap_read(sai->regmap, FSL_SAI_xCSR(tx), &xcsr);
+ regmap_read(sai->regmap,
+ FSL_SAI_xCSR(tx, ofs), &xcsr);
} while (--count && xcsr & FSL_SAI_CSR_TERE);
- regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs),
FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
- regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs),
FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
/*
@@ -575,13 +583,13 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
*/
if (!sai->is_slave_mode) {
/* Software Reset for both Tx and Rx */
- regmap_write(sai->regmap,
- FSL_SAI_TCSR, FSL_SAI_CSR_SR);
- regmap_write(sai->regmap,
- FSL_SAI_RCSR, FSL_SAI_CSR_SR);
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs),
+ FSL_SAI_CSR_SR);
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs),
+ FSL_SAI_CSR_SR);
/* Clear SR bit to finish the reset */
- regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
- regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
}
}
break;
@@ -596,10 +604,11 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned int ofs = sai->soc_data->reg_offset;
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
int ret;
- regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx),
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
FSL_SAI_CR3_TRCE_MASK,
FSL_SAI_CR3_TRCE);
@@ -613,9 +622,10 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned int ofs = sai->soc_data->reg_offset;
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx),
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
FSL_SAI_CR3_TRCE_MASK, 0);
}
@@ -633,18 +643,20 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
+ unsigned int ofs = sai->soc_data->reg_offset;
/* Software Reset for both Tx and Rx */
- regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
- regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR);
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
/* Clear SR bit to finish the reset */
- regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
- regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
- regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK,
+ regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs),
+ FSL_SAI_CR1_RFW_MASK,
sai->soc_data->fifo_depth - FSL_SAI_MAXBURST_TX);
- regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK,
- FSL_SAI_MAXBURST_RX - 1);
+ regmap_update_bits(sai->regmap, FSL_SAI_RCR1(ofs),
+ FSL_SAI_CR1_RFW_MASK, FSL_SAI_MAXBURST_RX - 1);
snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
&sai->dma_params_rx);
@@ -681,12 +693,12 @@ static const struct snd_soc_component_driver fsl_component = {
.name = "fsl-sai",
};
-static struct reg_default fsl_sai_reg_defaults[] = {
- {FSL_SAI_TCR1, 0},
- {FSL_SAI_TCR2, 0},
- {FSL_SAI_TCR3, 0},
- {FSL_SAI_TCR4, 0},
- {FSL_SAI_TCR5, 0},
+static struct reg_default fsl_sai_reg_defaults_ofs0[] = {
+ {FSL_SAI_TCR1(0), 0},
+ {FSL_SAI_TCR2(0), 0},
+ {FSL_SAI_TCR3(0), 0},
+ {FSL_SAI_TCR4(0), 0},
+ {FSL_SAI_TCR5(0), 0},
{FSL_SAI_TDR0, 0},
{FSL_SAI_TDR1, 0},
{FSL_SAI_TDR2, 0},
@@ -695,24 +707,50 @@ static struct reg_default fsl_sai_reg_defaults[] = {
{FSL_SAI_TDR5, 0},
{FSL_SAI_TDR6, 0},
{FSL_SAI_TDR7, 0},
- {FSL_SAI_TMR, 0},
- {FSL_SAI_RCR1, 0},
- {FSL_SAI_RCR2, 0},
- {FSL_SAI_RCR3, 0},
- {FSL_SAI_RCR4, 0},
- {FSL_SAI_RCR5, 0},
- {FSL_SAI_RMR, 0},
+ {FSL_SAI_TMR, 0},
+ {FSL_SAI_RCR1(0), 0},
+ {FSL_SAI_RCR2(0), 0},
+ {FSL_SAI_RCR3(0), 0},
+ {FSL_SAI_RCR4(0), 0},
+ {FSL_SAI_RCR5(0), 0},
+ {FSL_SAI_RMR, 0},
+};
+
+static struct reg_default fsl_sai_reg_defaults_ofs8[] = {
+ {FSL_SAI_TCR1(8), 0},
+ {FSL_SAI_TCR2(8), 0},
+ {FSL_SAI_TCR3(8), 0},
+ {FSL_SAI_TCR4(8), 0},
+ {FSL_SAI_TCR5(8), 0},
+ {FSL_SAI_TDR0, 0},
+ {FSL_SAI_TDR1, 0},
+ {FSL_SAI_TDR2, 0},
+ {FSL_SAI_TDR3, 0},
+ {FSL_SAI_TDR4, 0},
+ {FSL_SAI_TDR5, 0},
+ {FSL_SAI_TDR6, 0},
+ {FSL_SAI_TDR7, 0},
+ {FSL_SAI_TMR, 0},
+ {FSL_SAI_RCR1(8), 0},
+ {FSL_SAI_RCR2(8), 0},
+ {FSL_SAI_RCR3(8), 0},
+ {FSL_SAI_RCR4(8), 0},
+ {FSL_SAI_RCR5(8), 0},
+ {FSL_SAI_RMR, 0},
};
static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
{
+ struct fsl_sai *sai = dev_get_drvdata(dev);
+ unsigned int ofs = sai->soc_data->reg_offset;
+
+ if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
+ return true;
+
+ if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
+ return true;
+
switch (reg) {
- case FSL_SAI_TCSR:
- case FSL_SAI_TCR1:
- case FSL_SAI_TCR2:
- case FSL_SAI_TCR3:
- case FSL_SAI_TCR4:
- case FSL_SAI_TCR5:
case FSL_SAI_TFR0:
case FSL_SAI_TFR1:
case FSL_SAI_TFR2:
@@ -722,12 +760,6 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
case FSL_SAI_TFR6:
case FSL_SAI_TFR7:
case FSL_SAI_TMR:
- case FSL_SAI_RCSR:
- case FSL_SAI_RCR1:
- case FSL_SAI_RCR2:
- case FSL_SAI_RCR3:
- case FSL_SAI_RCR4:
- case FSL_SAI_RCR5:
case FSL_SAI_RDR0:
case FSL_SAI_RDR1:
case FSL_SAI_RDR2:
@@ -753,9 +785,13 @@ static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
{
+ struct fsl_sai *sai = dev_get_drvdata(dev);
+ unsigned int ofs = sai->soc_data->reg_offset;
+
+ if (reg == FSL_SAI_TCSR(ofs) || reg == FSL_SAI_RCSR(ofs))
+ return true;
+
switch (reg) {
- case FSL_SAI_TCSR:
- case FSL_SAI_RCSR:
case FSL_SAI_TFR0:
case FSL_SAI_TFR1:
case FSL_SAI_TFR2:
@@ -788,13 +824,16 @@ static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
{
+ struct fsl_sai *sai = dev_get_drvdata(dev);
+ unsigned int ofs = sai->soc_data->reg_offset;
+
+ if (reg >= FSL_SAI_TCSR(ofs) && reg <= FSL_SAI_TCR5(ofs))
+ return true;
+
+ if (reg >= FSL_SAI_RCSR(ofs) && reg <= FSL_SAI_RCR5(ofs))
+ return true;
+
switch (reg) {
- case FSL_SAI_TCSR:
- case FSL_SAI_TCR1:
- case FSL_SAI_TCR2:
- case FSL_SAI_TCR3:
- case FSL_SAI_TCR4:
- case FSL_SAI_TCR5:
case FSL_SAI_TDR0:
case FSL_SAI_TDR1:
case FSL_SAI_TDR2:
@@ -804,12 +843,6 @@ static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
case FSL_SAI_TDR6:
case FSL_SAI_TDR7:
case FSL_SAI_TMR:
- case FSL_SAI_RCSR:
- case FSL_SAI_RCR1:
- case FSL_SAI_RCR2:
- case FSL_SAI_RCR3:
- case FSL_SAI_RCR4:
- case FSL_SAI_RCR5:
case FSL_SAI_RMR:
return true;
default:
@@ -817,15 +850,15 @@ static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
}
}
-static const struct regmap_config fsl_sai_regmap_config = {
+static struct regmap_config fsl_sai_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.fast_io = true,
.max_register = FSL_SAI_RMR,
- .reg_defaults = fsl_sai_reg_defaults,
- .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults),
+ .reg_defaults = fsl_sai_reg_defaults_ofs0,
+ .num_reg_defaults = ARRAY_SIZE(fsl_sai_reg_defaults_ofs0),
.readable_reg = fsl_sai_readable_reg,
.volatile_reg = fsl_sai_volatile_reg,
.writeable_reg = fsl_sai_writeable_reg,
@@ -857,6 +890,12 @@ static int fsl_sai_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
+ if (sai->soc_data->reg_offset == 8) {
+ fsl_sai_regmap_config.reg_defaults = fsl_sai_reg_defaults_ofs8;
+ fsl_sai_regmap_config.num_reg_defaults =
+ ARRAY_SIZE(fsl_sai_reg_defaults_ofs8);
+ }
+
sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
"bus", base, &fsl_sai_regmap_config);
@@ -971,11 +1010,13 @@ static int fsl_sai_remove(struct platform_device *pdev)
static const struct fsl_sai_soc_data fsl_sai_vf610_data = {
.use_imx_pcm = false,
.fifo_depth = 32,
+ .reg_offset = 0,
};
static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = {
.use_imx_pcm = true,
.fifo_depth = 32,
+ .reg_offset = 0,
};
static const struct of_device_id fsl_sai_ids[] = {
@@ -1008,6 +1049,7 @@ static int fsl_sai_runtime_suspend(struct device *dev)
static int fsl_sai_runtime_resume(struct device *dev)
{
struct fsl_sai *sai = dev_get_drvdata(dev);
+ unsigned int ofs = sai->soc_data->reg_offset;
int ret;
ret = clk_prepare_enable(sai->bus_clk);
@@ -1029,11 +1071,11 @@ static int fsl_sai_runtime_resume(struct device *dev)
}
regcache_cache_only(sai->regmap, false);
- regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
- regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR);
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR);
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR);
usleep_range(1000, 2000);
- regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
- regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
+ regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
+ regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
ret = regcache_sync(sai->regmap);
if (ret)
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index 20c5b9b1e8bc..b89b0ca26053 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -14,12 +14,12 @@
SNDRV_PCM_FMTBIT_S32_LE)
/* SAI Register Map Register */
-#define FSL_SAI_TCSR 0x00 /* SAI Transmit Control */
-#define FSL_SAI_TCR1 0x04 /* SAI Transmit Configuration 1 */
-#define FSL_SAI_TCR2 0x08 /* SAI Transmit Configuration 2 */
-#define FSL_SAI_TCR3 0x0c /* SAI Transmit Configuration 3 */
-#define FSL_SAI_TCR4 0x10 /* SAI Transmit Configuration 4 */
-#define FSL_SAI_TCR5 0x14 /* SAI Transmit Configuration 5 */
+#define FSL_SAI_TCSR(ofs) (0x00 + ofs) /* SAI Transmit Control */
+#define FSL_SAI_TCR1(ofs) (0x04 + ofs) /* SAI Transmit Configuration 1 */
+#define FSL_SAI_TCR2(ofs) (0x08 + ofs) /* SAI Transmit Configuration 2 */
+#define FSL_SAI_TCR3(ofs) (0x0c + ofs) /* SAI Transmit Configuration 3 */
+#define FSL_SAI_TCR4(ofs) (0x10 + ofs) /* SAI Transmit Configuration 4 */
+#define FSL_SAI_TCR5(ofs) (0x14 + ofs) /* SAI Transmit Configuration 5 */
#define FSL_SAI_TDR0 0x20 /* SAI Transmit Data 0 */
#define FSL_SAI_TDR1 0x24 /* SAI Transmit Data 1 */
#define FSL_SAI_TDR2 0x28 /* SAI Transmit Data 2 */
@@ -37,12 +37,12 @@
#define FSL_SAI_TFR6 0x58 /* SAI Transmit FIFO 6 */
#define FSL_SAI_TFR7 0x5C /* SAI Transmit FIFO 7 */
#define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */
-#define FSL_SAI_RCSR 0x80 /* SAI Receive Control */
-#define FSL_SAI_RCR1 0x84 /* SAI Receive Configuration 1 */
-#define FSL_SAI_RCR2 0x88 /* SAI Receive Configuration 2 */
-#define FSL_SAI_RCR3 0x8c /* SAI Receive Configuration 3 */
-#define FSL_SAI_RCR4 0x90 /* SAI Receive Configuration 4 */
-#define FSL_SAI_RCR5 0x94 /* SAI Receive Configuration 5 */
+#define FSL_SAI_RCSR(ofs) (0x80 + ofs) /* SAI Receive Control */
+#define FSL_SAI_RCR1(ofs) (0x84 + ofs)/* SAI Receive Configuration 1 */
+#define FSL_SAI_RCR2(ofs) (0x88 + ofs) /* SAI Receive Configuration 2 */
+#define FSL_SAI_RCR3(ofs) (0x8c + ofs) /* SAI Receive Configuration 3 */
+#define FSL_SAI_RCR4(ofs) (0x90 + ofs) /* SAI Receive Configuration 4 */
+#define FSL_SAI_RCR5(ofs) (0x94 + ofs) /* SAI Receive Configuration 5 */
#define FSL_SAI_RDR0 0xa0 /* SAI Receive Data 0 */
#define FSL_SAI_RDR1 0xa4 /* SAI Receive Data 1 */
#define FSL_SAI_RDR2 0xa8 /* SAI Receive Data 2 */
@@ -61,14 +61,14 @@
#define FSL_SAI_RFR7 0xdc /* SAI Receive FIFO 7 */
#define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */
-#define FSL_SAI_xCSR(tx) (tx ? FSL_SAI_TCSR : FSL_SAI_RCSR)
-#define FSL_SAI_xCR1(tx) (tx ? FSL_SAI_TCR1 : FSL_SAI_RCR1)
-#define FSL_SAI_xCR2(tx) (tx ? FSL_SAI_TCR2 : FSL_SAI_RCR2)
-#define FSL_SAI_xCR3(tx) (tx ? FSL_SAI_TCR3 : FSL_SAI_RCR3)
-#define FSL_SAI_xCR4(tx) (tx ? FSL_SAI_TCR4 : FSL_SAI_RCR4)
-#define FSL_SAI_xCR5(tx) (tx ? FSL_SAI_TCR5 : FSL_SAI_RCR5)
-#define FSL_SAI_xDR(tx) (tx ? FSL_SAI_TDR : FSL_SAI_RDR)
-#define FSL_SAI_xFR(tx) (tx ? FSL_SAI_TFR : FSL_SAI_RFR)
+#define FSL_SAI_xCSR(tx, ofs) (tx ? FSL_SAI_TCSR(ofs) : FSL_SAI_RCSR(ofs))
+#define FSL_SAI_xCR1(tx, ofs) (tx ? FSL_SAI_TCR1(ofs) : FSL_SAI_RCR1(ofs))
+#define FSL_SAI_xCR2(tx, ofs) (tx ? FSL_SAI_TCR2(ofs) : FSL_SAI_RCR2(ofs))
+#define FSL_SAI_xCR3(tx, ofs) (tx ? FSL_SAI_TCR3(ofs) : FSL_SAI_RCR3(ofs))
+#define FSL_SAI_xCR4(tx, ofs) (tx ? FSL_SAI_TCR4(ofs) : FSL_SAI_RCR4(ofs))
+#define FSL_SAI_xCR5(tx, ofs) (tx ? FSL_SAI_TCR5(ofs) : FSL_SAI_RCR5(ofs))
+#define FSL_SAI_xDR(tx, ofs) (tx ? FSL_SAI_TDR(ofs) : FSL_SAI_RDR(ofs))
+#define FSL_SAI_xFR(tx, ofs) (tx ? FSL_SAI_TFR(ofs) : FSL_SAI_RFR(ofs))
#define FSL_SAI_xMR(tx) (tx ? FSL_SAI_TMR : FSL_SAI_RMR)
/* SAI Transmit/Receive Control Register */
@@ -158,6 +158,7 @@
struct fsl_sai_soc_data {
bool use_imx_pcm;
unsigned int fifo_depth;
+ unsigned int reg_offset;
};
struct fsl_sai {
--
2.20.1
^ permalink raw reply related
* Applied "ASoC: fsl_sai: Update Tx/Rx channel enable mask" to the asoc tree
From: Mark Brown @ 2019-08-07 13:30 UTC (permalink / raw)
To: Daniel Baluta
Cc: alsa-devel, angus, broonie, devicetree, festevam, kernel,
linux-imx, linux-kernel, l.stach
In-Reply-To: <20190806151214.6783-3-daniel.baluta@nxp.com>
The patch
ASoC: fsl_sai: Update Tx/Rx channel enable mask
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.4
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From b84f50b0fcb497a62068926fca793d2d213c7dbd Mon Sep 17 00:00:00 2001
From: Daniel Baluta <daniel.baluta@nxp.com>
Date: Tue, 6 Aug 2019 18:12:11 +0300
Subject: [PATCH] ASoC: fsl_sai: Update Tx/Rx channel enable mask
Tx channel enable (TCE) / Rx channel enable (RCE) bits
enable corresponding data channel for Tx/Rx operation.
Because SAI supports up the 8 channels TCE/RCE occupy
up the 8 bits inside TCR3/RCR3 registers we need to extend
the mask to reflect this.
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Acked-by: Nicolin Chen <nicoleotsuka@gmail.com>
Link: https://lore.kernel.org/r/20190806151214.6783-3-daniel.baluta@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/fsl/fsl_sai.c | 6 ++++--
sound/soc/fsl/fsl_sai.h | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index e4221f2a5ee3..f2698c94c9fe 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -599,7 +599,8 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
int ret;
- regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE,
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx),
+ FSL_SAI_CR3_TRCE_MASK,
FSL_SAI_CR3_TRCE);
ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
@@ -614,7 +615,8 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, 0);
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx),
+ FSL_SAI_CR3_TRCE_MASK, 0);
}
static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index 4bb478041d67..20c5b9b1e8bc 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -110,6 +110,7 @@
/* SAI Transmit and Receive Configuration 3 Register */
#define FSL_SAI_CR3_TRCE BIT(16)
+#define FSL_SAI_CR3_TRCE_MASK GENMASK(23, 16)
#define FSL_SAI_CR3_WDFL(x) (x)
#define FSL_SAI_CR3_WDFL_MASK 0x1f
--
2.20.1
^ permalink raw reply related
* Applied "ASoC: fsl_sai: Add support for imx7ulp/imx8mq" to the asoc tree
From: Mark Brown @ 2019-08-07 13:30 UTC (permalink / raw)
To: Daniel Baluta
Cc: alsa-devel, angus, broonie, devicetree, festevam, kernel,
linux-imx, linux-kernel, l.stach
In-Reply-To: <20190806151214.6783-5-daniel.baluta@nxp.com>
The patch
ASoC: fsl_sai: Add support for imx7ulp/imx8mq
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.4
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From a860fac420971c5a90d4f78959b44ead793aee4f Mon Sep 17 00:00:00 2001
From: Daniel Baluta <daniel.baluta@nxp.com>
Date: Tue, 6 Aug 2019 18:12:13 +0300
Subject: [PATCH] ASoC: fsl_sai: Add support for imx7ulp/imx8mq
SAI module on imx7ulp/imx8m features 2 new registers (VERID and PARAM)
at the beginning of register address space.
On imx7ulp FIFOs can held up to 16 x 32 bit samples.
On imx8mq FIFOs can held up to 128 x 32 bit samples.
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Acked-by: Nicolin Chen <nicoleotsuka@gmail.com>
Link: https://lore.kernel.org/r/20190806151214.6783-5-daniel.baluta@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/fsl/fsl_sai.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 0c5452927c04..4a346fcb5630 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -1019,10 +1019,24 @@ static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = {
.reg_offset = 0,
};
+static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = {
+ .use_imx_pcm = true,
+ .fifo_depth = 16,
+ .reg_offset = 8,
+};
+
+static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = {
+ .use_imx_pcm = true,
+ .fifo_depth = 128,
+ .reg_offset = 8,
+};
+
static const struct of_device_id fsl_sai_ids[] = {
{ .compatible = "fsl,vf610-sai", .data = &fsl_sai_vf610_data },
{ .compatible = "fsl,imx6sx-sai", .data = &fsl_sai_imx6sx_data },
{ .compatible = "fsl,imx6ul-sai", .data = &fsl_sai_imx6sx_data },
+ { .compatible = "fsl,imx7ulp-sai", .data = &fsl_sai_imx7ulp_data },
+ { .compatible = "fsl,imx8mq-sai", .data = &fsl_sai_imx8mq_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fsl_sai_ids);
--
2.20.1
^ permalink raw reply related
* Re: [PATCH 3/5] serial: lantiq: Make IRQ & ISR assignment dynamic
From: Andy Shevchenko @ 2019-08-07 13:29 UTC (permalink / raw)
To: Rahul Tanwar
Cc: linux-serial, devicetree, gregkh, linux-kernel, jslaby, robh+dt,
mark.rutland, qi-ming.wu, cheol.yong.kim, rahul.tanwar
In-Reply-To: <6dd57ea99f734bd4e413f6913914c0a93c00f295.1565160764.git.rahul.tanwar@linux.intel.com>
On Wed, Aug 07, 2019 at 05:21:33PM +0800, Rahul Tanwar wrote:
> This driver/IP is reused across multiple SoCs. Older SoCs supported three
> separate IRQs for tx, rx & err interrupts. Newer Lightning Mountain SoC
> supports single IRQ for all of tx/rx/err interrupts. This patch modifies
> the driver design to support dynamic assignment of IRQ resources & ISRs
> based on devicetree node compatible entries.
> +struct ltq_soc_data {
> + int (*fetch_irq)(struct platform_device *pdev,
> + struct ltq_uart_port *ltq_port);
This can be simple
int (*fetch_irq)(struct device *dev, struct ltq_uart_port *ltq_port);
(Note one line and struct device instead of platform_device)
> + int (*request_irq)(struct uart_port *port);
> + void (*free_irq)(struct uart_port *port);
> +};
> + retval = ltq_port->soc->request_irq(port);
> + if(retval)
Space is missed.
> return retval;
> +static int fetch_irq_lantiq(struct platform_device *pdev,
> + struct ltq_uart_port *ltq_port)
> +{
> + struct device_node *node = pdev->dev.of_node;
> + struct uart_port *port = <q_port->port;
> + struct resource irqres[3];
> + int ret;
> +
> + ret = of_irq_to_resource_table(node, irqres, 3);
> + if (ret != 3) {
> + dev_err(&pdev->dev,
> + "failed to get IRQs for serial port\n");
> + return -ENODEV;
> + }
> + ltq_port->tx_irq = irqres[0].start;
> + ltq_port->rx_irq = irqres[1].start;
> + ltq_port->err_irq = irqres[2].start;
> + port->irq = irqres[0].start;
> +
> + return ret;
I'm not sure you need to return known value. 0 will be good enough...
> +}
> + ltq_port->soc = of_device_get_match_data(&pdev->dev);
> + ret = ltq_port->soc->fetch_irq(pdev, ltq_port);
> + if (ret < 0)
...and thus simple...
if (ret)
...may be used.
> + return ret;
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [RFC,v3 7/9] media: platform: Add Mediatek ISP P1 device driver
From: Tomasz Figa @ 2019-08-07 13:25 UTC (permalink / raw)
To: Jungo Lin
Cc: devicetree, Sean Cheng (鄭昇弘),
Mauro Carvalho Chehab, Rynn Wu (吳育恩),
srv_heupstream, Rob Herring, Ryan Yu (余孟修),
Frankie Chiu (邱文凱), Hans Verkuil,
Matthias Brugger, Sj Huang,
moderated list:ARM/Mediatek SoC support, Laurent Pinchart,
ddavenport, Frederic Chen (陳俊元)
In-Reply-To: <1565143899.9157.19.camel@mtksdccf07>
On Wed, Aug 7, 2019 at 11:11 AM Jungo Lin <jungo.lin@mediatek.com> wrote:
>
> Hi, Tomasz:
>
> On Tue, 2019-08-06 at 18:47 +0900, Tomasz Figa wrote:
> > Hi Jungo,
> >
> > On Fri, Jul 26, 2019 at 4:24 PM Jungo Lin <jungo.lin@mediatek.com> wrote:
> > >
> > > Hi, Tomasz:
> > >
> > > On Thu, 2019-07-25 at 18:23 +0900, Tomasz Figa wrote:
> > > > .Hi Jungo,
> > > >
> > > > On Sat, Jul 20, 2019 at 6:58 PM Jungo Lin <jungo.lin@mediatek.com> wrote:
> > > > >
> > > > > Hi, Tomasz:
> > > > >
> > > > > On Wed, 2019-07-10 at 18:56 +0900, Tomasz Figa wrote:
> > > > > > Hi Jungo,
> > > > > >
> > > > > > On Tue, Jun 11, 2019 at 11:53:42AM +0800, Jungo Lin wrote:
> > [snip]
>
> I just keep some questions to be clarified.
> [snip]
>
> > > > > > > + isp_dev->meta0_vb2_index = meta0_vb2_index;
> > > > > > > + isp_dev->meta1_vb2_index = meta1_vb2_index;
> > > > > > > + } else {
> > > > > > > + if (irq_status & SOF_INT_ST) {
> > > > > > > + isp_dev->current_frame = hw_frame_num;
> > > > > > > + isp_dev->meta0_vb2_index = meta0_vb2_index;
> > > > > > > + isp_dev->meta1_vb2_index = meta1_vb2_index;
> > > > > > > + }
> > > > > > > + irq_handle_notify_event(isp_dev, irq_status, dma_status, 1);
> > > > > > > + }
> > > > > >
> > > > > > The if and else blocks do almost the same things just in different order. Is
> > > > > > it really expected?
> > > > > >
> > > > >
> > > > > If we receive HW_PASS1_DON_ST & SOF_INT_ST IRQ events at the same time,
> > > > > the correct sequence should be handle HW_PASS1_DON_ST firstly to check
> > > > > any de-queued frame and update the next frame setting later.
> > > > > Normally, this is a corner case or system performance issue.
> > > >
> > > > So it sounds like HW_PASS1_DON_ST means that all data from current
> > > > frame has been written, right? If I understand your explanation above
> > > > correctly, that would mean following handling of each interrupt:
> > > >
> > > > HW_PASS1_DON_ST:
> > > > - CQ executes with next CQ buffer to prepare for next frame. <- how
> > > > is this handled? does the CQ hardware automatically receive this event
> > > > from the ISP hadware?
> > > > - return VB2 buffers,
> > > > - complete requests.
> > > >
> > > > SOF_INT_ST:
> > > > - send VSYNC event to userspace,
> > > > - program next CQ buffer to CQ,
> > > >
> > > > SW_PASS1_DON_ST:
> > > > - reclaim CQ buffer and enqueue next frame to composing if available
> > > >
> > >
> > > Sorry for our implementation of HW_PASS1_DON_ST.
> > > It is confusing.
> > > Below is the revised version based on your conclusion.
> > > So in our new implemmenation, we just handle SOF_INT_ST &
> > > SW_PASS1_DON_ST events. We just add one warning message for
> > > HW_PASS1_DON_ST
> > >
> > > HW_PASS1_DON_ST:
> > > - CQ executes with next CQ buffer to prepare for next frame.
> > >
> > > SOF_INT_ST:
> > > - send VSYNC event to userspace,
> > > - program next CQ buffer to CQ,
> > >
> > > SW_PASS1_DON_ST:
> > > - reclaim CQ buffer and enqueue next frame to composing if available
> > > - return VB2 buffers,
> > > - complete requests.
> > >
> > > For CQ HW operations, it is listed below:
> > >
> > > a. The CQ buffer has two kinds of information
> > > - Which ISP registers needs to be updated.
> > > - Where the corresponding ISP register data to be read.
> > > b. The CQ buffer loading procedure is triggered by HW_PASS1_DONT_ST IRQ
> > > event periodically.
> > > - Normally, if the ISP HW receives the completed frame and it will
> > > trigger W_PASS1_DONT_ST IRQ and perform CQ buffer loading immediately.
> > > - So the CQ buffer loading is performed by ISP HW automatically.
> > > c. The ISP HW will read CQ base address register(REG_CQ_THR0_BASEADDR)
> > > to decide which CQ buffer is loaded.
> > > - So we configure the next CQ base address in SOF.
> > > d. For CQ buffer loading, CQ will read the ISP registers from CQ buffer
> > > and update the ISP register values into HW.
> > > - SCP composer will compose one dummy CQ buffer and assign it to
> > > REG_CQ_THR0_BASEADDR of each CQ buffer.
> > > - Dummy CQ buffer has no updated ISP registers comparing with other
> > > CQ buffers.
> > > - With this design, if there is no updated new CQ buffer by driver
> > > which may be caused no en-queue frames from user space. The CQ HW will
> > > load dummy CQ buffer and do nothing.
> >
> > Does the set of registers programmed by CQ include destination buffer
> > addresses to? If yes, we would end up overwriting previous frames if
> > no new buffers are provided.
> >
>
> Yes, the buffer addresses are changed per frame request. We need to
> compose CQ to include these DMA destination addresses. For your concern,
> we have DMA flow buffer control (FBC) in HW. If there is no FBC counter
> increased due to no buffer for each DMA, the ISP HW doesn't output the
> data to the corresponding DMA address.
>
> Below is the simple descriptor of CQ buffer.
> a. ISP registers in tuning buffer, including 3A registers.
> b. All capture buffers informations.
> - DMA buffer destination address
> - FBC counter
> c. Some specif ISP registers for meta DMAs, such as LCE or LMVO.
> d. frame sequence number register
>
Okay, with the FBC counter it sounds fine. Thanks for clarifying.
> > > f. The CQ buffer loading is guaranteed by HW to finish before the next
> > > SOF.
> > >
> >
> > Okay, thanks a lot for the explanation. This is much more clear now.
> >
> > [snip]
> > > > > > > +static const struct dev_pm_ops mtk_isp_pm_ops = {
> > > > > > > + SET_SYSTEM_SLEEP_PM_OPS(mtk_isp_suspend, mtk_isp_resume)
> > > > > > > + SET_RUNTIME_PM_OPS(mtk_isp_suspend, mtk_isp_resume, NULL)
> > > > > >
> > > > > > For V4L2 drivers system and runtime PM ops would normally be completely
> > > > > > different. Runtime PM ops would be called when the hardware is idle already
> > > > > > or is about to become active. System PM ops would be called at system power
> > > > > > state change and the hardware might be both idle or active. Please also see
> > > > > > my comments to mtk_isp_suspend() and mtk_isp_resume() above.
> > > > > >
> > > > >
> > > > > Here is the new implementation. It should be clear to show the
> > > > > difference between system and runtime PM ops.
> > > > >
> > > > > static const struct dev_pm_ops mtk_isp_pm_ops = {
> > > > > SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> > > > > pm_runtime_force_resume)
> > > > > SET_RUNTIME_PM_OPS(mtk_isp_runtime_suspend, mtk_isp_runtime_resume,
> > > > > NULL)
> > > > > };
> > > >
> > > > That's still not correct. In runtime suspend/resume ops we already are
> > > > not streaming anymore, because we call pm_runtime_get/put_*() when
> > > > starting and stopping streaming. In system suspend/resume ops we might
> > > > be streaming and that's when we need to stop the hardware and wait for
> > > > it to finish. Please implement these ops separately.
> > > >
> > > > Best regards,
> > > > Tomasz
> > >
> > >
> > > Ok, got your point.
> > > Below is the new implementation for your review.
> > >
> > > static int mtk_isp_pm_suspend(struct device *dev)
> > > {
> > > struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
> > > u32 val;
> > > int ret;
> > >
> > > dev_dbg(dev, "- %s\n", __func__);
> > >
> > > /* Check ISP is streaming or not */
> > > if (!p1_dev->cam_dev.streaming)
> > > goto done;
> >
> > We would normally check here for pm_runtime_suspended(). Although they
> > both should be equivalent. Still, there is no need to call
> > pm_runtime_force_suspend() if the latter is true, so we could just
> > return 0 instantly.
> >
>
> Ok, here is the fixed version.
>
> static int mtk_isp_pm_suspend(struct device *dev)
> {
> struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
> u32 val;
> int ret;
>
> dev_dbg(dev, "- %s\n", __func__);
>
> if (pm_runtime_suspended(dev))
> return 0;
>
> /* Disable ISP's view finder and wait for TG idle */
> dev_dbg(dev, "cam suspend, disable VF\n");
> val = readl(p1_dev->regs + REG_TG_VF_CON);
> writel(val & (~TG_VF_CON_VFDATA_EN), p1_dev->regs + REG_TG_VF_CON);
> ret = readl_poll_timeout_atomic(p1_dev->regs + REG_TG_INTER_ST, val,
> (val & TG_CS_MASK) == TG_IDLE_ST,
> USEC_PER_MSEC, MTK_ISP_STOP_HW_TIMEOUT);
> if (ret)
> dev_warn(dev, "can't stop HW:%d:0x%x\n", ret, val);
What happens in this case? Is it safe to continue?
>
> /* Disable CMOS */
> val = readl(p1_dev->regs + REG_TG_SEN_MODE);
> writel(val & (~TG_SEN_MODE_CMOS_EN), p1_dev->regs + REG_TG_SEN_MODE);
>
> /* Force ISP HW to idle */
> ret = pm_runtime_force_suspend(dev);
> if (ret)
> return ret;
We should probably reenable the hardware if the above failed, so that
we hopefully end up in the same state as before the suspend.
>
> return 0;
> }
> [snip]
>
> > > static int mtk_isp_pm_resume(struct device *dev)
> > > {
> > > struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
> > > u32 val;
> > > int ret;
> > >
> > > dev_dbg(dev, "- %s\n", __func__);
> > >
> > > /* Force ISP HW to resume if needed */
> > > ret = pm_runtime_force_resume(dev);
> > > if (ret)
> > > return ret;
> >
> > We should do this conditionally based on what pm_runtime_suspended()
> > returns. If it's non-zero then we can just return 0 instantly.
> >
>
> Ok, here is the fixed version.
>
> static int mtk_isp_pm_resume(struct device *dev)
> {
> struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
> u32 val;
> int ret;
>
> dev_dbg(dev, "- %s\n", __func__);
>
> if (pm_runtime_suspended(dev))
> return 0;
>
> /* Force ISP HW to resume */
> ret = pm_runtime_force_resume(dev);
> if (ret)
> return ret;
>
> /* Enable CMOS */
> dev_dbg(dev, "cam resume, enable CMOS/VF\n");
> val = readl(p1_dev->regs + REG_TG_SEN_MODE);
> writel(val | TG_SEN_MODE_CMOS_EN, p1_dev->regs + REG_TG_SEN_MODE);
>
> /* Enable VF */
> val = readl(p1_dev->regs + REG_TG_VF_CON);
> writel(val | TG_VF_CON_VFDATA_EN, p1_dev->regs + REG_TG_VF_CON);
>
> return 0;
> }
>
> [snip]
>
> > > static int mtk_isp_runtime_suspend(struct device *dev)
> > > {
> > > struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
> > >
> > > dev_dbg(dev, "- %s\n", __func__);
> > >
> > > if (pm_runtime_suspended(dev))
> > > return 0;
> >
> > Sorry, I guess I wasn't clear in my reply. It's not possible to get
> > this callback called if the device is already runtime suspended.
> >
>
> Ok, got it. Need to remove pm_runtime_suspended(dev) checking and move
> it into mtk_isp_pm_* functions. If I still don't get your point, could
> you kindly provide one sample driver for reference?
The above implementation is okay, thanks. :)
> Based on current
> implementation, it is similar to below drivers.
> https://elixir.bootlin.com/linux/latest/source/drivers/media/platform/mtk-mdp/mtk_mdp_core.c#L255
> https://elixir.bootlin.com/linux/latest/source/drivers/media/platform/exynos4-is/fimc-is-i2c.c#L113
>
The first one is an m2m device so it has slightly different rules -
the runtime PM is allowed to suspend between frames if the idle time
is long enough. The second one is a dummy driver for some fake i2c
bus, so it doesn't really have any meaningful implementation.
I think you could take a look at
https://elixir.bootlin.com/linux/v5.3-rc3/source/drivers/media/platform/exynos4-is/fimc-lite.c#L1550
, which is an online capture device too.
>
> static int mtk_isp_runtime_suspend(struct device *dev)
> {
> struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
>
> dev_dbg(dev, "%s:disable clock\n", __func__);
> clk_bulk_disable_unprepare(p1_dev->num_clks, p1_dev->clks);
>
> return 0;
> }
>
> [snip]
>
> > > static int mtk_isp_runtime_resume(struct device *dev)
> > > {
> > > struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
> > > int ret;
> > >
> > > dev_dbg(dev, "- %s\n", __func__);
> > >
> > > if (pm_runtime_suspended(dev))
> > > return 0;
> >
> > In this case the above call would always return non-zero, so the
> > behavior wouldn't be very good.
> >
>
> Same as above.
>
> static int mtk_isp_runtime_resume(struct device *dev)
> {
> struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
> int ret;
>
> dev_dbg(dev, "%s:enable clock\n", __func__);
> ret = clk_bulk_prepare_enable(p1_dev->num_clks, p1_dev->clks);
> if (ret) {
> dev_err(dev, "failed to enable clock:%d\n", ret);
> return ret;
> }
>
> return 0;
> }
Makes sense, thanks!
Best regards,
Tomasz
^ permalink raw reply
* [PATCH] of: irq: fix a trivial typo in a doc comment
From: Lubomir Rintel @ 2019-08-07 13:22 UTC (permalink / raw)
To: Jiri Kosina
Cc: Rob Herring, Frank Rowand, devicetree, linux-kernel,
Lubomir Rintel
Diverged from what the code does with commit 530210c7814e ("of/irq: Replace
of_irq with of_phandle_args").
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
drivers/of/irq.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 7f84bb4903caa..a296eaf52a5b2 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -277,7 +277,7 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw);
* of_irq_parse_one - Resolve an interrupt for a device
* @device: the device whose interrupt is to be resolved
* @index: index of the interrupt to resolve
- * @out_irq: structure of_irq filled by this function
+ * @out_irq: structure of_phandle_args filled by this function
*
* This function resolves an interrupt for a node by walking the interrupt tree,
* finding which interrupt controller node it is attached to, and returning the
--
2.21.0
^ permalink raw reply related
* Re: [PATCH 2/5] serial: lantiq: Use proper DT compatible string
From: Andy Shevchenko @ 2019-08-07 13:20 UTC (permalink / raw)
To: Rahul Tanwar
Cc: linux-serial, devicetree, gregkh, linux-kernel, jslaby, robh+dt,
mark.rutland, qi-ming.wu, cheol.yong.kim, rahul.tanwar
In-Reply-To: <12c3029f406ca1fedf14154154f7082e358f0473.1565160764.git.rahul.tanwar@linux.intel.com>
On Wed, Aug 07, 2019 at 05:21:32PM +0800, Rahul Tanwar wrote:
> The patch adds change to use explicit string instead of a macro for
> DT compatible string.
For consistency you may need to convert OF_EARLYCON_DECLARE() as well.
Perhaps commit message should explain the rationale, i.e. the following patches
will add another compatible string and thus it makes sense to have them
explicitly mentioned.
> Suggested-by: Andy Shevchenko <andriy.shevchenko@intel.com>
> Signed-off-by: Rahul Tanwar <rahul.tanwar@linux.intel.com>
> ---
> drivers/tty/serial/lantiq.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
> index 42e27b48e9cc..1116261c973e 100644
> --- a/drivers/tty/serial/lantiq.c
> +++ b/drivers/tty/serial/lantiq.c
> @@ -792,7 +792,7 @@ lqasc_probe(struct platform_device *pdev)
> }
>
> static const struct of_device_id ltq_asc_match[] = {
> - { .compatible = DRVNAME },
> + { .compatible = "lantiq,asc" },
> {},
> };
>
> --
> 2.11.0
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 06/16] net: phy: adin: support PHY mode converters
From: Andrew Lunn @ 2019-08-07 13:20 UTC (permalink / raw)
To: Ardelean, Alexandru
Cc: davem@davemloft.net, hkallweit1@gmail.com, mark.rutland@arm.com,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org, f.fainelli@gmail.com, robh+dt@kernel.org
In-Reply-To: <7747cb845a9122004b9565f444b4719170f74b35.camel@analog.com>
> Is it ok if we defer the solution for this drivers/patchset?
Yes, not a problem if phy-mode means phy-mode.
Andrew
^ permalink raw reply
* Re: [PATCH 1/5] serial: lantiq: Add SMP support
From: Andy Shevchenko @ 2019-08-07 13:19 UTC (permalink / raw)
To: Rahul Tanwar
Cc: linux-serial, devicetree, gregkh, linux-kernel, jslaby, robh+dt,
mark.rutland, qi-ming.wu, cheol.yong.kim, rahul.tanwar
In-Reply-To: <7912786cccad60c72b20ea724af1def505ab22aa.1565160764.git.rahul.tanwar@linux.intel.com>
On Wed, Aug 07, 2019 at 05:21:31PM +0800, Rahul Tanwar wrote:
> The existing driver can only support single core SoC. But new multicore
> platforms which reuse the same driver/IP need SMP support. This patch adds
> multicore support in the driver.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
>
> Signed-off-by: Rahul Tanwar <rahul.tanwar@linux.intel.com>
> ---
> drivers/tty/serial/lantiq.c | 47 ++++++++++++++++++++++++++++++---------------
> 1 file changed, 32 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
> index 9de9f0f239a1..42e27b48e9cc 100644
> --- a/drivers/tty/serial/lantiq.c
> +++ b/drivers/tty/serial/lantiq.c
> @@ -99,7 +99,6 @@
> static void lqasc_tx_chars(struct uart_port *port);
> static struct ltq_uart_port *lqasc_port[MAXPORTS];
> static struct uart_driver lqasc_reg;
> -static DEFINE_SPINLOCK(ltq_asc_lock);
>
> struct ltq_uart_port {
> struct uart_port port;
> @@ -110,6 +109,7 @@ struct ltq_uart_port {
> unsigned int tx_irq;
> unsigned int rx_irq;
> unsigned int err_irq;
> + spinlock_t lock; /* exclusive access for multi core */
> };
>
> static inline void asc_update_bits(u32 clear, u32 set, void __iomem *reg)
> @@ -135,9 +135,11 @@ static void
> lqasc_start_tx(struct uart_port *port)
> {
> unsigned long flags;
> - spin_lock_irqsave(<q_asc_lock, flags);
> + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
> +
> + spin_lock_irqsave(<q_port->lock, flags);
> lqasc_tx_chars(port);
> - spin_unlock_irqrestore(<q_asc_lock, flags);
> + spin_unlock_irqrestore(<q_port->lock, flags);
> return;
> }
>
> @@ -245,9 +247,11 @@ lqasc_tx_int(int irq, void *_port)
> {
> unsigned long flags;
> struct uart_port *port = (struct uart_port *)_port;
> - spin_lock_irqsave(<q_asc_lock, flags);
> + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
> +
> + spin_lock_irqsave(<q_port->lock, flags);
> __raw_writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
> - spin_unlock_irqrestore(<q_asc_lock, flags);
> + spin_unlock_irqrestore(<q_port->lock, flags);
> lqasc_start_tx(port);
> return IRQ_HANDLED;
> }
> @@ -257,11 +261,13 @@ lqasc_err_int(int irq, void *_port)
> {
> unsigned long flags;
> struct uart_port *port = (struct uart_port *)_port;
> - spin_lock_irqsave(<q_asc_lock, flags);
> + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
> +
> + spin_lock_irqsave(<q_port->lock, flags);
> /* clear any pending interrupts */
> asc_update_bits(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE |
> ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE);
> - spin_unlock_irqrestore(<q_asc_lock, flags);
> + spin_unlock_irqrestore(<q_port->lock, flags);
> return IRQ_HANDLED;
> }
>
> @@ -270,10 +276,12 @@ lqasc_rx_int(int irq, void *_port)
> {
> unsigned long flags;
> struct uart_port *port = (struct uart_port *)_port;
> - spin_lock_irqsave(<q_asc_lock, flags);
> + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
> +
> + spin_lock_irqsave(<q_port->lock, flags);
> __raw_writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
> lqasc_rx_chars(port);
> - spin_unlock_irqrestore(<q_asc_lock, flags);
> + spin_unlock_irqrestore(<q_port->lock, flags);
> return IRQ_HANDLED;
> }
>
> @@ -307,11 +315,13 @@ lqasc_startup(struct uart_port *port)
> {
> struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
> int retval;
> + unsigned long flags;
>
> if (!IS_ERR(ltq_port->clk))
> clk_prepare_enable(ltq_port->clk);
> port->uartclk = clk_get_rate(ltq_port->freqclk);
>
> + spin_lock_irqsave(<q_port->lock, flags);
> asc_update_bits(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
> port->membase + LTQ_ASC_CLC);
>
> @@ -331,6 +341,8 @@ lqasc_startup(struct uart_port *port)
> asc_update_bits(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN |
> ASCCON_ROEN, port->membase + LTQ_ASC_CON);
>
> + spin_unlock_irqrestore(<q_port->lock, flags);
> +
> retval = request_irq(ltq_port->tx_irq, lqasc_tx_int,
> 0, "asc_tx", port);
> if (retval) {
> @@ -367,15 +379,19 @@ static void
> lqasc_shutdown(struct uart_port *port)
> {
> struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
> + unsigned long flags;
> +
> free_irq(ltq_port->tx_irq, port);
> free_irq(ltq_port->rx_irq, port);
> free_irq(ltq_port->err_irq, port);
>
> + spin_lock_irqsave(<q_port->lock, flags);
> __raw_writel(0, port->membase + LTQ_ASC_CON);
> asc_update_bits(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
> port->membase + LTQ_ASC_RXFCON);
> asc_update_bits(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
> port->membase + LTQ_ASC_TXFCON);
> + spin_unlock_irqrestore(<q_port->lock, flags);
> if (!IS_ERR(ltq_port->clk))
> clk_disable_unprepare(ltq_port->clk);
> }
> @@ -390,6 +406,7 @@ lqasc_set_termios(struct uart_port *port,
> unsigned int baud;
> unsigned int con = 0;
> unsigned long flags;
> + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
>
> cflag = new->c_cflag;
> iflag = new->c_iflag;
> @@ -443,7 +460,7 @@ lqasc_set_termios(struct uart_port *port,
> /* set error signals - framing, parity and overrun, enable receiver */
> con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN;
>
> - spin_lock_irqsave(<q_asc_lock, flags);
> + spin_lock_irqsave(<q_port->lock, flags);
>
> /* set up CON */
> asc_update_bits(0, con, port->membase + LTQ_ASC_CON);
> @@ -471,7 +488,7 @@ lqasc_set_termios(struct uart_port *port,
> /* enable rx */
> __raw_writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
>
> - spin_unlock_irqrestore(<q_asc_lock, flags);
> + spin_unlock_irqrestore(<q_port->lock, flags);
>
> /* Don't rewrite B0 */
> if (tty_termios_baud_rate(new))
> @@ -589,17 +606,14 @@ lqasc_console_putchar(struct uart_port *port, int ch)
> static void lqasc_serial_port_write(struct uart_port *port, const char *s,
> u_int count)
> {
> - unsigned long flags;
> -
> - spin_lock_irqsave(<q_asc_lock, flags);
> uart_console_write(port, s, count, lqasc_console_putchar);
> - spin_unlock_irqrestore(<q_asc_lock, flags);
> }
>
> static void
> lqasc_console_write(struct console *co, const char *s, u_int count)
> {
> struct ltq_uart_port *ltq_port;
> + unsigned long flags;
>
> if (co->index >= MAXPORTS)
> return;
> @@ -608,7 +622,9 @@ lqasc_console_write(struct console *co, const char *s, u_int count)
> if (!ltq_port)
> return;
>
> + spin_lock_irqsave(<q_port->lock, flags);
> lqasc_serial_port_write(<q_port->port, s, count);
> + spin_unlock_irqrestore(<q_port->lock, flags);
> }
>
> static int __init
> @@ -766,6 +782,7 @@ lqasc_probe(struct platform_device *pdev)
> ltq_port->rx_irq = irqres[1].start;
> ltq_port->err_irq = irqres[2].start;
>
> + spin_lock_init(<q_port->lock);
> lqasc_port[line] = ltq_port;
> platform_set_drvdata(pdev, ltq_port);
>
> --
> 2.11.0
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 4/5] dt-bindings: serial: lantiq: Update for new SoC
From: Andy Shevchenko @ 2019-08-07 13:17 UTC (permalink / raw)
To: Rahul Tanwar
Cc: linux-serial, devicetree, gregkh, linux-kernel, jslaby, robh+dt,
mark.rutland, qi-ming.wu, cheol.yong.kim, rahul.tanwar
In-Reply-To: <47c6565f5537575b16f65ca5ccc5ecfc61818dbc.1565160764.git.rahul.tanwar@linux.intel.com>
On Wed, Aug 07, 2019 at 05:21:34PM +0800, Rahul Tanwar wrote:
> There is a new Intel Atom based Lightning Mountain(LGM) network processor SoC which
> reuses Lantiq ASC serial controller IP. This patch adds new compatible string
> and its expected property value in order to support the driver for LGM as well.
I think it makes sense to convert to YAML before adding new properties.
>
> Signed-off-by: Rahul Tanwar <rahul.tanwar@linux.intel.com>
> ---
> Documentation/devicetree/bindings/serial/lantiq_asc.txt | 17 +++++++++++++++--
> 1 file changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/serial/lantiq_asc.txt b/Documentation/devicetree/bindings/serial/lantiq_asc.txt
> index 40e81a5818f6..18b45dd13a61 100644
> --- a/Documentation/devicetree/bindings/serial/lantiq_asc.txt
> +++ b/Documentation/devicetree/bindings/serial/lantiq_asc.txt
> @@ -1,10 +1,14 @@
> Lantiq SoC ASC serial controller
>
> Required properties:
> -- compatible : Should be "lantiq,asc"
> +- compatible : Should be "lantiq,asc" or "intel,lgm-asc"
> - reg : Address and length of the register set for the device
> -- interrupts: the 3 (tx rx err) interrupt numbers. The interrupt specifier
> +- interrupts:
> + For "lantiq,asc" - the 3 (tx rx err) interrupt numbers. The interrupt specifier
> depends on the interrupt-parent interrupt controller.
> + or
> + For "intel,lgm-asc" - the common interrupt number for all of tx rx & err interrupts
> + followed by level/sense specifier.
>
> Optional properties:
> - clocks: Should contain frequency clock and gate clock
> @@ -29,3 +33,12 @@ asc1: serial@e100c00 {
> interrupt-parent = <&icu0>;
> interrupts = <112 113 114>;
> };
> +
> +asc0: serial@e0a00000 {
> + compatible = "intel,lgm-asc";
> + reg = <0xe0a00000 0x1000>;
> + interrupt-parent = <&ioapic1>;
> + interrupts = <128 1>;
> + clocks = <&cgu0 LGM_CLK_NOC4>, <&cgu0 LGM_GCLK_ASC0>;
> + clock-names = "freq", "asc";
> +};
> --
> 2.11.0
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v7 01/20] pinctrl: tegra: Add suspend and resume support
From: Linus Walleij @ 2019-08-07 13:11 UTC (permalink / raw)
To: Sowjanya Komatineni
Cc: thierry.reding@gmail.com, Jon Hunter, Thomas Gleixner,
Jason Cooper, Marc Zyngier, Stefan Agner, Mark Rutland,
Peter De Schrijver, Prashant Gaikwad, Stephen Boyd, linux-clk,
open list:GPIO SUBSYSTEM, jckuo, Joseph Lo, talho, linux-tegra,
linux-kernel@vger.kernel.org, Mikko Perttunen, spatra,
Rob Herring, Dmitry Osipenko <dig>
In-Reply-To: <dadf0cc7-fba4-9ab5-6ac9-0c8699eb4401@nvidia.com>
On Wed, Aug 7, 2019 at 5:40 AM Sowjanya Komatineni
<skomatineni@nvidia.com> wrote:
> On 8/6/19 2:51 PM, Sowjanya Komatineni wrote:
> >
> > On 8/5/19 2:20 AM, Linus Walleij wrote:
> >> On Wed, Jul 31, 2019 at 11:11 PM Sowjanya Komatineni
> >> <skomatineni@nvidia.com> wrote:
> >>
> >>> This patch adds support for Tegra pinctrl driver suspend and resume.
> >>>
> >>> During suspend, context of all pinctrl registers are stored and
> >>> on resume they are all restored to have all the pinmux and pad
> >>> configuration for normal operation.
> >>>
> >>> Acked-by: Thierry Reding <treding@nvidia.com>
> >>> Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
> >>> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
> >> Patch applied to the pinctrl tree.
> >>
> >> This patch seems finished.
> >>
> >> Also if the rest don't get merged for v5.4 then at least this is so
> >> your patch stack gets more shallow.
> >>
> >> I hope it's fine to merge this separately, else tell me and I'll
> >> pull it out.
> >>
> >> Yours,
> >> Linus Walleij
> >
> > Yes, this patch can be merged separately. But, there's latest feedback
> > from Dmitry to add barrier after writes to make sure pinmux register
> > writes happen.
> >
> > So will update this patch to add barrier in v8. So, need to wait for v8.
> >
> > Thanks
> >
> > Sowjanya
> >
> I see it merged. So will exclude suspend/resume patch and will add patch
> for necessary write barrier fix in v8 version.
Yeah just make an incremental patch, that's fine.
If you want to overdo it you can add a Fixes: tag to
the original patch, but I don't care much.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v8 02/14] media: doc: add document for rkisp1 meta buffer format
From: Sakari Ailus @ 2019-08-07 13:09 UTC (permalink / raw)
To: Helen Koike
Cc: linux-rockchip, devicetree, eddie.cai.linux, mchehab, heiko,
jacob2.chen, jeffy.chen, zyc, linux-kernel, tfiga, hans.verkuil,
laurent.pinchart, kernel, ezequiel, linux-media, linux-arm-kernel,
zhengsq, Jacob Chen
In-Reply-To: <20190730184256.30338-3-helen.koike@collabora.com>
Hi Helen,
On Tue, Jul 30, 2019 at 03:42:44PM -0300, Helen Koike wrote:
> From: Jacob Chen <jacob2.chen@rock-chips.com>
>
> This commit add document for rkisp1 meta buffer format
>
> Signed-off-by: Jacob Chen <jacob-chen@rock-chips.com>
> Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
> [update for upstream]
> Signed-off-by: Helen Koike <helen.koike@collabora.com>
>
> ---
>
> Changes in v8:
> - Add SPDX in the header
> - Remove emacs configs
> - Fix doc style
>
> Changes in v7:
> - s/correspond/corresponding
> - s/use/uses
> - s/docuemnt/document
>
> Documentation/media/uapi/v4l/meta-formats.rst | 2 ++
> .../uapi/v4l/pixfmt-meta-rkisp1-params.rst | 23 +++++++++++++++++++
> .../uapi/v4l/pixfmt-meta-rkisp1-stat.rst | 22 ++++++++++++++++++
> 3 files changed, 47 insertions(+)
> create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
> create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
>
> diff --git a/Documentation/media/uapi/v4l/meta-formats.rst b/Documentation/media/uapi/v4l/meta-formats.rst
> index b10ca9ee3968..5de621fea3cc 100644
> --- a/Documentation/media/uapi/v4l/meta-formats.rst
> +++ b/Documentation/media/uapi/v4l/meta-formats.rst
> @@ -24,3 +24,5 @@ These formats are used for the :ref:`metadata` interface only.
> pixfmt-meta-uvc
> pixfmt-meta-vsp1-hgo
> pixfmt-meta-vsp1-hgt
> + pixfmt-meta-rkisp1-params
> + pixfmt-meta-rkisp1-stat
> diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
> new file mode 100644
> index 000000000000..103b5cb79b7c
> --- /dev/null
> +++ b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-params.rst
> @@ -0,0 +1,23 @@
> +.. SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +
> +.. _v4l2-meta-fmt-rkisp1-params:
> +
> +============================
> +V4L2_META_FMT_RK_ISP1_PARAMS
> +============================
> +
> +Rockchip ISP1 Parameters Data
> +
> +Description
> +===========
> +
> +This format describes input parameters for the Rockchip ISP1.
> +
> +It uses c-struct :c:type:`rkisp1_isp_params_cfg`, which is defined in
> +the ``linux/rkisp1-config.h`` header file.
Do you have an insight on in which order the device executes the processing
steps for the image data? The pipeline may not be entirely linear either
(statistics, for instance). This should be included in the documentation.
> +
> +The parameters consist of multiple modules.
> +The module won't be updated if the corresponding bit was not set in module_*_update.
> +
> +.. kernel-doc:: include/uapi/linux/rkisp1-config.h
> + :functions: rkisp1_isp_params_cfg
> diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
> new file mode 100644
> index 000000000000..4ad303f96421
> --- /dev/null
> +++ b/Documentation/media/uapi/v4l/pixfmt-meta-rkisp1-stat.rst
> @@ -0,0 +1,22 @@
> +.. SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +
> +.. _v4l2-meta-fmt-rkisp1-stat:
> +
> +=============================
> +V4L2_META_FMT_RK_ISP1_STAT_3A
> +=============================
> +
> +
> +Rockchip ISP1 Statistics Data
> +
> +Description
> +===========
> +
> +This format describes image color statistics information generated by the Rockchip
> +ISP1.
> +
> +It uses c-struct :c:type:`rkisp1_stat_buffer`, which is defined in
> +the ``linux/rkisp1-config.h`` header file.
> +
> +.. kernel-doc:: include/uapi/linux/rkisp1-config.h
> + :functions: rkisp1_stat_buffer
--
Kind regards,
Sakari Ailus
sakari.ailus@linux.intel.com
^ permalink raw reply
* Re: [PATCH v8 04/14] media: rkisp1: add Rockchip MIPI Synopsys DPHY driver
From: Sakari Ailus @ 2019-08-07 13:05 UTC (permalink / raw)
To: Helen Koike
Cc: linux-rockchip, devicetree, eddie.cai.linux, mchehab, heiko,
jacob2.chen, jeffy.chen, zyc, linux-kernel, tfiga, hans.verkuil,
laurent.pinchart, sakari.ailus, kernel, ezequiel, linux-media,
linux-arm-kernel, zhengsq
In-Reply-To: <20190730184256.30338-5-helen.koike@collabora.com>
Hi Helen,
Thanks for the patchset.
On Tue, Jul 30, 2019 at 03:42:46PM -0300, Helen Koike wrote:
> From: Jacob Chen <jacob2.chen@rock-chips.com>
>
> This commit adds a subdev driver for Rockchip MIPI Synopsys DPHY driver
>
> Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
> Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>
> Signed-off-by: Tomasz Figa <tfiga@chromium.org>
> [migrate to phy framework]
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> [update for upstream]
> Signed-off-by: Helen Koike <helen.koike@collabora.com>
>
> ---
>
> Changes in v8:
> - Remove boiler plate license text
>
> Changes in v7:
> - Migrate dphy specific code from
> drivers/media/platform/rockchip/isp1/mipi_dphy_sy.c
> to drivers/phy/rockchip/phy-rockchip-dphy.c
> - Drop support for rk3288
> - Drop support for dphy txrx
> - code styling and checkpatch fixes
>
> drivers/phy/rockchip/Kconfig | 8 +
> drivers/phy/rockchip/Makefile | 1 +
> drivers/phy/rockchip/phy-rockchip-dphy.c | 408 +++++++++++++++++++++++
> 3 files changed, 417 insertions(+)
> create mode 100644 drivers/phy/rockchip/phy-rockchip-dphy.c
>
> diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
> index c454c90cd99e..afd072f135e6 100644
> --- a/drivers/phy/rockchip/Kconfig
> +++ b/drivers/phy/rockchip/Kconfig
> @@ -9,6 +9,14 @@ config PHY_ROCKCHIP_DP
> help
> Enable this to support the Rockchip Display Port PHY.
>
> +config PHY_ROCKCHIP_DPHY
> + tristate "Rockchip MIPI Synopsys DPHY driver"
> + depends on ARCH_ROCKCHIP && OF
How about (...) || COMPILE_TEST ?
> + select GENERIC_PHY_MIPI_DPHY
> + select GENERIC_PHY
> + help
> + Enable this to support the Rockchip MIPI Synopsys DPHY.
> +
> config PHY_ROCKCHIP_EMMC
> tristate "Rockchip EMMC PHY Driver"
> depends on ARCH_ROCKCHIP && OF
> diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
> index fd21cbaf40dd..f62e9010bcaf 100644
> --- a/drivers/phy/rockchip/Makefile
> +++ b/drivers/phy/rockchip/Makefile
> @@ -1,5 +1,6 @@
> # SPDX-License-Identifier: GPL-2.0
> obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o
> +obj-$(CONFIG_PHY_ROCKCHIP_DPHY) += phy-rockchip-dphy.o
> obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
> obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o
> obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
> diff --git a/drivers/phy/rockchip/phy-rockchip-dphy.c b/drivers/phy/rockchip/phy-rockchip-dphy.c
> new file mode 100644
> index 000000000000..3a29976c2dff
> --- /dev/null
> +++ b/drivers/phy/rockchip/phy-rockchip-dphy.c
> @@ -0,0 +1,408 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Rockchip MIPI Synopsys DPHY driver
> + *
> + * Based on:
> + *
> + * Copyright (C) 2016 FuZhou Rockchip Co., Ltd.
> + * Author: Yakir Yang <ykk@@rock-chips.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/phy/phy.h>
> +#include <linux/phy/phy-mipi-dphy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#define RK3399_GRF_SOC_CON9 0x6224
> +#define RK3399_GRF_SOC_CON21 0x6254
> +#define RK3399_GRF_SOC_CON22 0x6258
> +#define RK3399_GRF_SOC_CON23 0x625c
> +#define RK3399_GRF_SOC_CON24 0x6260
> +#define RK3399_GRF_SOC_CON25 0x6264
> +#define RK3399_GRF_SOC_STATUS1 0xe2a4
> +
> +#define CLOCK_LANE_HS_RX_CONTROL 0x34
> +#define LANE0_HS_RX_CONTROL 0x44
> +#define LANE1_HS_RX_CONTROL 0x54
> +#define LANE2_HS_RX_CONTROL 0x84
> +#define LANE3_HS_RX_CONTROL 0x94
> +#define HS_RX_DATA_LANES_THS_SETTLE_CONTROL 0x75
> +
> +#define MAX_DPHY_CLK 8
> +
> +#define PHY_TESTEN_ADDR (0x1 << 16)
> +#define PHY_TESTEN_DATA (0x0 << 16)
> +#define PHY_TESTCLK (0x1 << 1)
> +#define PHY_TESTCLR (0x1 << 0)
> +#define THS_SETTLE_COUNTER_THRESHOLD 0x04
> +
> +#define HIWORD_UPDATE(val, mask, shift) \
> + ((val) << (shift) | (mask) << ((shift) + 16))
> +
> +#define GRF_SOC_CON12 0x0274
> +
> +#define GRF_EDP_REF_CLK_SEL_INTER_HIWORD_MASK BIT(20)
> +#define GRF_EDP_REF_CLK_SEL_INTER BIT(4)
> +
> +#define GRF_EDP_PHY_SIDDQ_HIWORD_MASK BIT(21)
> +#define GRF_EDP_PHY_SIDDQ_ON 0
> +#define GRF_EDP_PHY_SIDDQ_OFF BIT(5)
> +
> +struct hsfreq_range {
> + u32 range_h;
> + u8 cfg_bit;
> +};
> +
> +static const struct hsfreq_range rk3399_mipidphy_hsfreq_ranges[] = {
> + { 89, 0x00}, { 99, 0x10}, { 109, 0x20}, { 129, 0x01},
> + { 139, 0x11}, { 149, 0x21}, { 169, 0x02}, { 179, 0x12},
> + { 199, 0x22}, { 219, 0x03}, { 239, 0x13}, { 249, 0x23},
> + { 269, 0x04}, { 299, 0x14}, { 329, 0x05}, { 359, 0x15},
> + { 399, 0x25}, { 449, 0x06}, { 499, 0x16}, { 549, 0x07},
> + { 599, 0x17}, { 649, 0x08}, { 699, 0x18}, { 749, 0x09},
> + { 799, 0x19}, { 849, 0x29}, { 899, 0x39}, { 949, 0x0a},
> + { 999, 0x1a}, {1049, 0x2a}, {1099, 0x3a}, {1149, 0x0b},
> + {1199, 0x1b}, {1249, 0x2b}, {1299, 0x3b}, {1349, 0x0c},
> + {1399, 0x1c}, {1449, 0x2c}, {1500, 0x3c}
> +};
> +
> +static const char * const rk3399_mipidphy_clks[] = {
> + "dphy-ref",
> + "dphy-cfg",
> + "grf",
> +};
> +
> +enum dphy_reg_id {
> + GRF_DPHY_RX0_TURNDISABLE = 0,
> + GRF_DPHY_RX0_FORCERXMODE,
> + GRF_DPHY_RX0_FORCETXSTOPMODE,
> + GRF_DPHY_RX0_ENABLE,
> + GRF_DPHY_RX0_TESTCLR,
> + GRF_DPHY_RX0_TESTCLK,
> + GRF_DPHY_RX0_TESTEN,
> + GRF_DPHY_RX0_TESTDIN,
> + GRF_DPHY_RX0_TURNREQUEST,
> + GRF_DPHY_RX0_TESTDOUT,
> + GRF_DPHY_TX0_TURNDISABLE,
> + GRF_DPHY_TX0_FORCERXMODE,
> + GRF_DPHY_TX0_FORCETXSTOPMODE,
> + GRF_DPHY_TX0_TURNREQUEST,
> + GRF_DPHY_TX1RX1_TURNDISABLE,
> + GRF_DPHY_TX1RX1_FORCERXMODE,
> + GRF_DPHY_TX1RX1_FORCETXSTOPMODE,
> + GRF_DPHY_TX1RX1_ENABLE,
> + GRF_DPHY_TX1RX1_MASTERSLAVEZ,
> + GRF_DPHY_TX1RX1_BASEDIR,
> + GRF_DPHY_TX1RX1_ENABLECLK,
> + GRF_DPHY_TX1RX1_TURNREQUEST,
> + GRF_DPHY_RX1_SRC_SEL,
> + /* rk3288 only */
> + GRF_CON_DISABLE_ISP,
> + GRF_CON_ISP_DPHY_SEL,
> + GRF_DSI_CSI_TESTBUS_SEL,
> + GRF_DVP_V18SEL,
> + /* below is for rk3399 only */
> + GRF_DPHY_RX0_CLK_INV_SEL,
> + GRF_DPHY_RX1_CLK_INV_SEL,
> +};
> +
> +struct dphy_reg {
> + u32 offset;
> + u32 mask;
> + u32 shift;
> +};
> +
> +#define PHY_REG(_offset, _width, _shift) \
> + { .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, }
> +
> +static const struct dphy_reg rk3399_grf_dphy_regs[] = {
> + [GRF_DPHY_RX0_TURNREQUEST] = PHY_REG(RK3399_GRF_SOC_CON9, 4, 0),
> + [GRF_DPHY_RX0_CLK_INV_SEL] = PHY_REG(RK3399_GRF_SOC_CON9, 1, 10),
> + [GRF_DPHY_RX1_CLK_INV_SEL] = PHY_REG(RK3399_GRF_SOC_CON9, 1, 11),
> + [GRF_DPHY_RX0_ENABLE] = PHY_REG(RK3399_GRF_SOC_CON21, 4, 0),
> + [GRF_DPHY_RX0_FORCERXMODE] = PHY_REG(RK3399_GRF_SOC_CON21, 4, 4),
> + [GRF_DPHY_RX0_FORCETXSTOPMODE] = PHY_REG(RK3399_GRF_SOC_CON21, 4, 8),
> + [GRF_DPHY_RX0_TURNDISABLE] = PHY_REG(RK3399_GRF_SOC_CON21, 4, 12),
> + [GRF_DPHY_TX0_FORCERXMODE] = PHY_REG(RK3399_GRF_SOC_CON22, 4, 0),
> + [GRF_DPHY_TX0_FORCETXSTOPMODE] = PHY_REG(RK3399_GRF_SOC_CON22, 4, 4),
> + [GRF_DPHY_TX0_TURNDISABLE] = PHY_REG(RK3399_GRF_SOC_CON22, 4, 8),
> + [GRF_DPHY_TX0_TURNREQUEST] = PHY_REG(RK3399_GRF_SOC_CON22, 4, 12),
> + [GRF_DPHY_TX1RX1_ENABLE] = PHY_REG(RK3399_GRF_SOC_CON23, 4, 0),
> + [GRF_DPHY_TX1RX1_FORCERXMODE] = PHY_REG(RK3399_GRF_SOC_CON23, 4, 4),
> + [GRF_DPHY_TX1RX1_FORCETXSTOPMODE] = PHY_REG(RK3399_GRF_SOC_CON23, 4, 8),
> + [GRF_DPHY_TX1RX1_TURNDISABLE] = PHY_REG(RK3399_GRF_SOC_CON23, 4, 12),
> + [GRF_DPHY_TX1RX1_TURNREQUEST] = PHY_REG(RK3399_GRF_SOC_CON24, 4, 0),
> + [GRF_DPHY_RX1_SRC_SEL] = PHY_REG(RK3399_GRF_SOC_CON24, 1, 4),
> + [GRF_DPHY_TX1RX1_BASEDIR] = PHY_REG(RK3399_GRF_SOC_CON24, 1, 5),
> + [GRF_DPHY_TX1RX1_ENABLECLK] = PHY_REG(RK3399_GRF_SOC_CON24, 1, 6),
> + [GRF_DPHY_TX1RX1_MASTERSLAVEZ] = PHY_REG(RK3399_GRF_SOC_CON24, 1, 7),
> + [GRF_DPHY_RX0_TESTDIN] = PHY_REG(RK3399_GRF_SOC_CON25, 8, 0),
> + [GRF_DPHY_RX0_TESTEN] = PHY_REG(RK3399_GRF_SOC_CON25, 1, 8),
> + [GRF_DPHY_RX0_TESTCLK] = PHY_REG(RK3399_GRF_SOC_CON25, 1, 9),
> + [GRF_DPHY_RX0_TESTCLR] = PHY_REG(RK3399_GRF_SOC_CON25, 1, 10),
> + [GRF_DPHY_RX0_TESTDOUT] = PHY_REG(RK3399_GRF_SOC_STATUS1, 8, 0),
> +};
> +
> +struct dphy_drv_data {
> + const char * const *clks;
> + int num_clks;
> + const struct hsfreq_range *hsfreq_ranges;
> + int num_hsfreq_ranges;
> + const struct dphy_reg *regs;
> +};
> +
> +struct rockchip_dphy {
> + struct device *dev;
> + struct regmap *grf;
> + const struct dphy_reg *grf_regs;
> + struct clk_bulk_data clks[MAX_DPHY_CLK];
> +
> + const struct dphy_drv_data *drv_data;
> + struct phy_configure_opts_mipi_dphy config;
> +};
> +
> +static inline void write_grf_reg(struct rockchip_dphy *priv,
> + int index, u8 value)
> +{
> + const struct dphy_reg *reg = &priv->grf_regs[index];
> + unsigned int val = HIWORD_UPDATE(value, reg->mask, reg->shift);
> +
> + WARN_ON(!reg->offset);
> + regmap_write(priv->grf, reg->offset, val);
> +}
> +
> +static void mipidphy0_wr_reg(struct rockchip_dphy *priv,
> + u8 test_code, u8 test_data)
> +{
> + /*
> + * With the falling edge on TESTCLK, the TESTDIN[7:0] signal content
> + * is latched internally as the current test code. Test data is
> + * programmed internally by rising edge on TESTCLK.
> + */
> + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 1);
> + write_grf_reg(priv, GRF_DPHY_RX0_TESTDIN, test_code);
> + write_grf_reg(priv, GRF_DPHY_RX0_TESTEN, 1);
> + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 0);
> + write_grf_reg(priv, GRF_DPHY_RX0_TESTEN, 0);
> + write_grf_reg(priv, GRF_DPHY_RX0_TESTDIN, test_data);
> + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 1);
> +}
> +
> +/* should be move to power_on */
> +static int mipidphy_rx_stream_on(struct rockchip_dphy *priv)
> +{
> + const struct dphy_drv_data *drv_data = priv->drv_data;
> + const struct hsfreq_range *hsfreq_ranges = drv_data->hsfreq_ranges;
> + struct phy_configure_opts_mipi_dphy *config = &priv->config;
> + unsigned int i, hsfreq = 0, data_rate_mbps = config->hs_clk_rate;
> + int num_hsfreq_ranges = drv_data->num_hsfreq_ranges;
> +
> + do_div(data_rate_mbps, 1000 * 1000);
> +
> + dev_dbg(priv->dev, "%s: lanes %d - data_rate_mbps %u\n",
> + __func__, config->lanes, data_rate_mbps);
> +
> + for (i = 0; i < num_hsfreq_ranges; i++) {
> + if (hsfreq_ranges[i].range_h >= data_rate_mbps) {
> + hsfreq = hsfreq_ranges[i].cfg_bit;
> + break;
> + }
> + }
> +
> + write_grf_reg(priv, GRF_DPHY_RX0_FORCERXMODE, 0);
> + write_grf_reg(priv, GRF_DPHY_RX0_FORCETXSTOPMODE, 0);
> +
> + /* Disable lan turn around, which is ignored in receive mode */
> + write_grf_reg(priv, GRF_DPHY_RX0_TURNREQUEST, 0);
> + write_grf_reg(priv, GRF_DPHY_RX0_TURNDISABLE, 0xf);
> +
> + write_grf_reg(priv, GRF_DPHY_RX0_ENABLE, GENMASK(config->lanes - 1, 0));
> +
> + /* dphy start */
> + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 1);
> + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLR, 1);
> + usleep_range(100, 150);
> + write_grf_reg(priv, GRF_DPHY_RX0_TESTCLR, 0);
> + usleep_range(100, 150);
> +
> + /* set clock lane */
> + /* HS hsfreq_range & lane 0 settle bypass */
> + mipidphy0_wr_reg(priv, CLOCK_LANE_HS_RX_CONTROL, 0);
> + /* HS RX Control of lane0 */
> + mipidphy0_wr_reg(priv, LANE0_HS_RX_CONTROL, hsfreq << 1);
> + /* HS RX Control of lane1 */
> + mipidphy0_wr_reg(priv, LANE1_HS_RX_CONTROL, 0);
> + /* HS RX Control of lane2 */
> + mipidphy0_wr_reg(priv, LANE2_HS_RX_CONTROL, 0);
> + /* HS RX Control of lane3 */
> + mipidphy0_wr_reg(priv, LANE3_HS_RX_CONTROL, 0);
> + /* HS RX Data Lanes Settle State Time Control */
> + mipidphy0_wr_reg(priv, HS_RX_DATA_LANES_THS_SETTLE_CONTROL,
> + THS_SETTLE_COUNTER_THRESHOLD);
> +
> + /* Normal operation */
> + mipidphy0_wr_reg(priv, 0x0, 0);
> +
> + return 0;
> +}
> +
> +static int rockchip_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
> +{
> + struct rockchip_dphy *priv = phy_get_drvdata(phy);
> + int ret;
> +
> + /* pass with phy_mipi_dphy_get_default_config (with pixel rate?) */
> + ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
> + if (ret)
> + return ret;
> +
> + memcpy(&priv->config, opts, sizeof(priv->config));
You could to:
priv->config = *opts;
Up to you. Some people like memcpy(). :-)
> +
> + return 0;
> +}
> +
> +static int rockchip_dphy_power_on(struct phy *phy)
> +{
> + struct rockchip_dphy *priv = phy_get_drvdata(phy);
> + int ret;
> +
> + ret = clk_bulk_enable(priv->drv_data->num_clks, priv->clks);
> + if (ret)
> + return ret;
> +
> + return mipidphy_rx_stream_on(priv);
> +}
> +
> +static int rockchip_dphy_power_off(struct phy *phy)
> +{
> + struct rockchip_dphy *priv = phy_get_drvdata(phy);
> +
> + clk_bulk_disable(priv->drv_data->num_clks, priv->clks);
> + return 0;
> +}
> +
> +static int rockchip_dphy_init(struct phy *phy)
> +{
> + struct rockchip_dphy *priv = phy_get_drvdata(phy);
> + int ret;
> +
> + ret = clk_bulk_prepare(priv->drv_data->num_clks, priv->clks);
return ...;
> + if (ret)
> + return ret;
> + return 0;
> +}
> +
> +static int rockchip_dphy_exit(struct phy *phy)
> +{
> + struct rockchip_dphy *priv = phy_get_drvdata(phy);
> +
> + clk_bulk_unprepare(priv->drv_data->num_clks, priv->clks);
> + return 0;
> +}
> +
> +static const struct phy_ops rockchip_dphy_ops = {
> + .power_on = rockchip_dphy_power_on,
> + .power_off = rockchip_dphy_power_off,
> + .init = rockchip_dphy_init,
> + .exit = rockchip_dphy_exit,
> + .configure = rockchip_dphy_configure,
> + .owner = THIS_MODULE,
> +};
> +
> +static const struct dphy_drv_data rk3399_mipidphy_drv_data = {
> + .clks = rk3399_mipidphy_clks,
> + .num_clks = ARRAY_SIZE(rk3399_mipidphy_clks),
> + .hsfreq_ranges = rk3399_mipidphy_hsfreq_ranges,
> + .num_hsfreq_ranges = ARRAY_SIZE(rk3399_mipidphy_hsfreq_ranges),
> + .regs = rk3399_grf_dphy_regs,
Do you expect to support more of the similar PHY(s) --- are there such? If
not, you could put these in the code that uses them.
> +};
> +
> +static const struct of_device_id rockchip_dphy_dt_ids[] = {
> + {
> + .compatible = "rockchip,rk3399-mipi-dphy",
> + .data = &rk3399_mipidphy_drv_data,
> + },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, rockchip_dphy_dt_ids);
> +
> +static int rockchip_dphy_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + const struct dphy_drv_data *drv_data;
> + struct phy_provider *phy_provider;
> + const struct of_device_id *of_id;
> + struct rockchip_dphy *priv;
> + struct regmap *grf;
> + struct phy *phy;
> + unsigned int i;
> + int ret;
> +
> + if (!dev->parent || !dev->parent->of_node)
> + return -ENODEV;
> +
> + if (platform_get_resource(pdev, IORESOURCE_MEM, 0)) {
> + dev_err(&pdev->dev, "Rockchip DPHY driver only suports rx\n");
> + return -EINVAL;
> + }
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> + priv->dev = dev;
> +
> + grf = syscon_node_to_regmap(dev->parent->of_node);
> + if (IS_ERR(grf)) {
> + grf = syscon_regmap_lookup_by_phandle(dev->of_node,
> + "rockchip,grf");
> + if (IS_ERR(grf)) {
> + dev_err(dev, "Can't find GRF syscon\n");
> + return -ENODEV;
> + }
> + }
> + priv->grf = grf;
> +
> + of_id = of_match_device(rockchip_dphy_dt_ids, dev);
> + if (!of_id)
> + return -EINVAL;
> +
> + drv_data = of_id->data;
> + priv->grf_regs = drv_data->regs;
> + priv->drv_data = drv_data;
> + for (i = 0; i < drv_data->num_clks; i++)
> + priv->clks[i].id = drv_data->clks[i];
> + ret = devm_clk_bulk_get(&pdev->dev, drv_data->num_clks, priv->clks);
> + if (ret)
> + return ret;
> +
> + phy = devm_phy_create(dev, np, &rockchip_dphy_ops);
> + if (IS_ERR(phy)) {
> + dev_err(dev, "failed to create phy\n");
> + return PTR_ERR(phy);
> + }
> + phy_set_drvdata(phy, priv);
> +
> + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> + return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static struct platform_driver rockchip_dphy_driver = {
> + .probe = rockchip_dphy_probe,
> + .driver = {
> + .name = "rockchip-mipi-dphy",
> + .of_match_table = rockchip_dphy_dt_ids,
> + },
> +};
> +module_platform_driver(rockchip_dphy_driver);
> +
> +MODULE_AUTHOR("Ezequiel Garcia <ezequiel@collabora.com>");
> +MODULE_DESCRIPTION("Rockchip MIPI Synopsys DPHY driver");
> +MODULE_LICENSE("Dual MIT/GPL");
--
Kind regards,
Sakari Ailus
^ permalink raw reply
* Re: [PATCH v4 2/3] OPP: Add support for bandwidth OPP tables
From: Georgi Djakov @ 2019-08-07 12:53 UTC (permalink / raw)
To: Saravana Kannan, Rob Herring, Mark Rutland, Viresh Kumar,
Nishanth Menon, Stephen Boyd, Rafael J. Wysocki
Cc: vincent.guittot, seansw, daidavid1, adharmap, Rajendra Nayak,
sibis, bjorn.andersson, evgreen, kernel-team, linux-pm,
devicetree, linux-kernel
In-Reply-To: <20190726231558.175130-3-saravanak@google.com>
Hi Saravana,
On 7/27/19 02:15, Saravana Kannan wrote:
> Not all devices quantify their performance points in terms of frequency.
> Devices like interconnects quantify their performance points in terms of
> bandwidth. We need a way to represent these bandwidth levels in OPP. So,
> add support for parsing bandwidth OPPs from DT.
>
> Signed-off-by: Saravana Kannan <saravanak@google.com>
> ---
> drivers/opp/of.c | 41 ++++++++++++++++++++++++++++++++---------
> drivers/opp/opp.h | 4 +++-
> 2 files changed, 35 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/opp/of.c b/drivers/opp/of.c
> index b313aca9894f..ac73512f4416 100644
> --- a/drivers/opp/of.c
> +++ b/drivers/opp/of.c
> @@ -523,6 +523,35 @@ void dev_pm_opp_of_remove_table(struct device *dev)
> }
> EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
>
> +static int _read_opp_key(struct dev_pm_opp *new_opp, struct device_node *np)
> +{
> + int ret;
> + u64 rate;
> + u32 bw;
> +
> + ret = of_property_read_u64(np, "opp-hz", &rate);
> + if (!ret) {
> + /*
> + * Rate is defined as an unsigned long in clk API, and so
> + * casting explicitly to its type. Must be fixed once rate is 64
> + * bit guaranteed in clk API.
> + */
> + new_opp->rate = (unsigned long)rate;
> + return 0;
So we can't have a single OPP table with both frequency and bandwidth?
> + }
> +
> + ret = of_property_read_u32(np, "opp-peak-KBps", &bw);
> + if (ret)
> + return ret;
> + new_opp->rate = (unsigned long) bw;
> +
> + ret = of_property_read_u32(np, "opp-avg-KBps", &bw);
> + if (!ret)
> + new_opp->avg_bw = (unsigned long) bw;
> +
> + return 0;
> +}
> +
> /**
> * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
> * @opp_table: OPP table
> @@ -560,22 +589,16 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
> if (!new_opp)
> return ERR_PTR(-ENOMEM);
>
> - ret = of_property_read_u64(np, "opp-hz", &rate);
> + ret = _read_opp_key(new_opp, np);
> if (ret < 0) {
> /* "opp-hz" is optional for devices like power domains. */
> if (!opp_table->is_genpd) {
> - dev_err(dev, "%s: opp-hz not found\n", __func__);
> + dev_err(dev, "%s: opp-hz or opp-peak-bw not found\n",
s/opp-peak-bw/opp-peak-kBps/
Thanks,
Georgi
^ permalink raw reply
* [RFC,v4,4/4] media: platform: Add Mediatek ISP P1 V4L2 device driver
From: Jungo Lin @ 2019-08-07 12:48 UTC (permalink / raw)
To: tfiga, hverkuil-cisco, laurent.pinchart, matthias.bgg, mchehab
Cc: shik, devicetree, Sean.Cheng, suleiman, Rynn.Wu, srv_heupstream,
robh, ryan.yu, Jerry-ch.Chen, frankie.chiu, jungo.lin, sj.huang,
yuzhao, linux-mediatek, zwisler, ddavenport, frederic.chen,
linux-arm-kernel, linux-media
In-Reply-To: <20190807124803.29884-1-jungo.lin@mediatek.com>
This patch adds the Mediatek ISP P1 HW control device driver.
It handles the ISP HW configuration, provides interrupt handling and
initializes the V4L2 device nodes and other V4L2 functions. Moreover,
implement standard V4L2 video driver that utilizes V4L2 and media
framework APIs. It supports one media device, one sub-device and
several video devices during initialization. Moreover, it also connects
with sensor and seninf drivers with V4L2 async APIs. Communicate with
co-process via SCP communication to compose ISP registers in the
firmware.
(The current metadata interface used in meta input and partial
meta nodes is only a temporary solution to kick off the driver
development and is not ready to be reviewed yet.)
Signed-off-by: Jungo Lin <jungo.lin@mediatek.com>
---
This patch depends on "Add support for mt8183 SCP"[1].
[1] https://patchwork.kernel.org/cover/11076543/
---
drivers/media/platform/Kconfig | 1 +
drivers/media/platform/Makefile | 1 +
drivers/media/platform/mtk-isp/Kconfig | 17 +
.../media/platform/mtk-isp/isp_50/Makefile | 3 +
.../platform/mtk-isp/isp_50/cam/Makefile | 6 +
.../platform/mtk-isp/isp_50/cam/mtk_cam-hw.c | 622 +++++
.../platform/mtk-isp/isp_50/cam/mtk_cam-hw.h | 65 +
.../platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h | 222 ++
.../mtk-isp/isp_50/cam/mtk_cam-regs.h | 95 +
.../platform/mtk-isp/isp_50/cam/mtk_cam.c | 2066 +++++++++++++++++
.../platform/mtk-isp/isp_50/cam/mtk_cam.h | 242 ++
11 files changed, 3340 insertions(+)
create mode 100644 drivers/media/platform/mtk-isp/Kconfig
create mode 100644 drivers/media/platform/mtk-isp/isp_50/Makefile
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/Makefile
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.c
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.h
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-regs.h
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.c
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.h
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 8a19654b393a..672e3a74412b 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -147,6 +147,7 @@ source "drivers/media/platform/xilinx/Kconfig"
source "drivers/media/platform/rcar-vin/Kconfig"
source "drivers/media/platform/atmel/Kconfig"
source "drivers/media/platform/sunxi/sun6i-csi/Kconfig"
+source "drivers/media/platform/mtk-isp/Kconfig"
config VIDEO_TI_CAL
tristate "TI CAL (Camera Adaptation Layer) driver"
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 7cbbd925124c..061e9ca6c456 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_VIDEO_MEDIATEK_MDP) += mtk-mdp/
obj-$(CONFIG_VIDEO_MEDIATEK_JPEG) += mtk-jpeg/
+obj-$(CONFIG_VIDEO_MEDIATEK_ISP_PASS1) += mtk-isp/isp_50/
obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss/
obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
diff --git a/drivers/media/platform/mtk-isp/Kconfig b/drivers/media/platform/mtk-isp/Kconfig
new file mode 100644
index 000000000000..8679e160ae7e
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/Kconfig
@@ -0,0 +1,17 @@
+config VIDEO_MEDIATEK_ISP_PASS1
+ tristate "Mediatek ISP Pass 1 driver"
+ depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ select V4L2_FWNODE
+ select VIDEOBUF2_VMALLOC
+ select VIDEOBUF2_DMA_CONTIG
+ select MTK_SCP
+ default n
+ help
+ Pass 1 driver controls 3A (auto-focus, exposure,
+ and white balance) with tuning feature and outputs
+ the captured image buffers in Mediatek's camera system.
+
+ Choose y if you want to use Mediatek SoCs to create image
+ captured application such as video recording and still image
+ capturing.
diff --git a/drivers/media/platform/mtk-isp/isp_50/Makefile b/drivers/media/platform/mtk-isp/isp_50/Makefile
new file mode 100644
index 000000000000..ce79d283b209
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_VIDEO_MEDIATEK_ISP_PASS1) += cam/
\ No newline at end of file
diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/Makefile b/drivers/media/platform/mtk-isp/isp_50/cam/Makefile
new file mode 100644
index 000000000000..53b54d3c26a0
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/cam/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+mtk-cam-isp-objs += mtk_cam.o
+mtk-cam-isp-objs += mtk_cam-hw.o
+
+obj-$(CONFIG_VIDEO_MEDIATEK_ISP_PASS1) += mtk-cam-isp.o
\ No newline at end of file
diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.c b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.c
new file mode 100644
index 000000000000..5625d694ea07
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.c
@@ -0,0 +1,622 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2019 MediaTek Inc.
+
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/module.h>
+#include <linux/platform_data/mtk_scp.h>
+#include <linux/pm_runtime.h>
+#include <linux/remoteproc.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+
+#include <media/v4l2-event.h>
+
+#include "mtk_cam.h"
+#include "mtk_cam-hw.h"
+#include "mtk_cam-regs.h"
+
+#define MTK_ISP_COMPOSER_MEM_SIZE 0x200000
+#define MTK_ISP_CQ_BUFFER_COUNT 3
+#define MTK_ISP_CQ_ADDRESS_OFFSET 0x640
+
+/*
+ *
+ * MTK Camera ISP P1 HW supports 3 ISP HW (CAM A/B/C).
+ * The T-put capability of CAM B is the maximum (max line buffer: 5376 pixels)
+ * For CAM A/C, it only supports max line buffer with 3328 pixels.
+ * In current driver, only supports CAM B.
+ *
+ */
+#define MTK_ISP_CAM_ID_B 3
+#define MTK_ISP_IPI_SEND_TIMEOUT 50
+#define MTK_ISP_STOP_HW_TIMEOUT (33 * USEC_PER_MSEC)
+
+static void isp_tx_frame_worker(struct work_struct *work)
+{
+ struct mtk_cam_dev_request *req =
+ container_of(work, struct mtk_cam_dev_request, frame_work);
+ struct mtk_cam_dev *cam =
+ container_of(req->req.mdev, struct mtk_cam_dev, media_dev);
+ struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(cam->dev);
+
+ scp_ipi_send(p1_dev->scp_pdev, SCP_IPI_ISP_FRAME, &req->frame_params,
+ sizeof(req->frame_params), MTK_ISP_IPI_SEND_TIMEOUT);
+}
+
+static void isp_composer_handler(void *data, unsigned int len, void *priv)
+{
+ struct mtk_isp_p1_device *p1_dev = (struct mtk_isp_p1_device *)priv;
+ struct device *dev = p1_dev->dev;
+ struct mtk_isp_scp_p1_cmd *ipi_msg;
+
+ ipi_msg = (struct mtk_isp_scp_p1_cmd *)data;
+
+ if (len < offsetofend(struct mtk_isp_scp_p1_cmd, ack_info)) {
+ dev_err(dev, "wrong IPI len:%d\n", len);
+ return;
+ }
+
+ if (ipi_msg->cmd_id != ISP_CMD_ACK ||
+ ipi_msg->ack_info.cmd_id != ISP_CMD_FRAME_ACK)
+ return;
+
+ p1_dev->composed_frame_seq_no = ipi_msg->ack_info.frame_seq_no;
+ dev_dbg(dev, "ack frame_num:%d\n", p1_dev->composed_frame_seq_no);
+}
+
+static int isp_composer_init(struct mtk_isp_p1_device *p1_dev)
+{
+ struct device *dev = p1_dev->dev;
+ int ret;
+
+ ret = scp_ipi_register(p1_dev->scp_pdev, SCP_IPI_ISP_CMD,
+ isp_composer_handler, p1_dev);
+ if (ret) {
+ dev_err(dev, "failed to register IPI cmd\n");
+ return ret;
+ }
+ ret = scp_ipi_register(p1_dev->scp_pdev, SCP_IPI_ISP_FRAME,
+ isp_composer_handler, p1_dev);
+ if (ret) {
+ dev_err(dev, "failed to register IPI frame\n");
+ goto unreg_ipi_cmd;
+ }
+
+ p1_dev->composer_wq =
+ alloc_ordered_workqueue(dev_name(p1_dev->dev),
+ __WQ_LEGACY | WQ_MEM_RECLAIM |
+ WQ_FREEZABLE);
+ if (!p1_dev->composer_wq) {
+ dev_err(dev, "failed to alloc composer workqueue\n");
+ goto unreg_ipi_frame;
+ }
+
+ return 0;
+
+unreg_ipi_frame:
+ scp_ipi_unregister(p1_dev->scp_pdev, SCP_IPI_ISP_FRAME);
+unreg_ipi_cmd:
+ scp_ipi_unregister(p1_dev->scp_pdev, SCP_IPI_ISP_CMD);
+
+ return ret;
+}
+
+static void isp_composer_uninit(struct mtk_isp_p1_device *p1_dev)
+{
+ destroy_workqueue(p1_dev->composer_wq);
+ scp_ipi_unregister(p1_dev->scp_pdev, SCP_IPI_ISP_CMD);
+ scp_ipi_unregister(p1_dev->scp_pdev, SCP_IPI_ISP_FRAME);
+}
+
+static void isp_composer_hw_init(struct mtk_isp_p1_device *p1_dev)
+{
+ struct mtk_isp_scp_p1_cmd composer_tx_cmd;
+
+ memset(&composer_tx_cmd, 0, sizeof(composer_tx_cmd));
+ composer_tx_cmd.cmd_id = ISP_CMD_INIT;
+ composer_tx_cmd.init_param.hw_module = MTK_ISP_CAM_ID_B;
+
+ /*
+ * Passed coherent reserved memory info. for SCP firmware usage.
+ * This buffer is used for SCP's ISP composer to compose.
+ * The size of is fixed to 0x200000 for the requirement of composer.
+ */
+ composer_tx_cmd.init_param.cq_addr.iova = p1_dev->composer_iova;
+ composer_tx_cmd.init_param.cq_addr.scp_addr = p1_dev->composer_scp_addr;
+
+ scp_ipi_send(p1_dev->scp_pdev, SCP_IPI_ISP_CMD, &composer_tx_cmd,
+ sizeof(composer_tx_cmd), MTK_ISP_IPI_SEND_TIMEOUT);
+}
+
+static void isp_composer_hw_deinit(struct mtk_isp_p1_device *p1_dev)
+{
+ struct mtk_isp_scp_p1_cmd composer_tx_cmd;
+
+ memset(&composer_tx_cmd, 0, sizeof(composer_tx_cmd));
+ composer_tx_cmd.cmd_id = ISP_CMD_DEINIT;
+
+ scp_ipi_send(p1_dev->scp_pdev, SCP_IPI_ISP_CMD, &composer_tx_cmd,
+ sizeof(composer_tx_cmd), MTK_ISP_IPI_SEND_TIMEOUT);
+
+ isp_composer_uninit(p1_dev);
+}
+
+void mtk_isp_hw_config(struct mtk_cam_dev *cam,
+ struct p1_config_param *config_param)
+{
+ struct mtk_isp_scp_p1_cmd composer_tx_cmd;
+ struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(cam->dev);
+
+ memset(&composer_tx_cmd, 0, sizeof(composer_tx_cmd));
+ composer_tx_cmd.cmd_id = ISP_CMD_CONFIG;
+ memcpy(&composer_tx_cmd.config_param, config_param,
+ sizeof(*config_param));
+
+ scp_ipi_send(p1_dev->scp_pdev, SCP_IPI_ISP_CMD, &composer_tx_cmd,
+ sizeof(composer_tx_cmd), MTK_ISP_IPI_SEND_TIMEOUT);
+}
+
+void mtk_isp_stream(struct mtk_cam_dev *cam, int on)
+{
+ struct mtk_isp_scp_p1_cmd composer_tx_cmd;
+ struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(cam->dev);
+
+ memset(&composer_tx_cmd, 0, sizeof(composer_tx_cmd));
+ composer_tx_cmd.cmd_id = ISP_CMD_STREAM;
+ composer_tx_cmd.is_stream_on = on;
+
+ scp_ipi_send(p1_dev->scp_pdev, SCP_IPI_ISP_CMD, &composer_tx_cmd,
+ sizeof(composer_tx_cmd), MTK_ISP_IPI_SEND_TIMEOUT);
+}
+
+int mtk_isp_hw_init(struct mtk_cam_dev *cam)
+{
+ struct device *dev = cam->dev;
+ struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
+ int ret;
+
+ ret = rproc_boot(p1_dev->rproc_handle);
+ if (ret) {
+ dev_err(dev, "failed to rproc_boot\n");
+ return ret;
+ }
+
+ ret = isp_composer_init(p1_dev);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_sync(dev);
+ isp_composer_hw_init(p1_dev);
+
+ p1_dev->enqueued_frame_seq_no = 0;
+ p1_dev->dequeued_frame_seq_no = 0;
+ p1_dev->composed_frame_seq_no = 0;
+ p1_dev->sof_count = 0;
+
+ dev_dbg(dev, "%s done\n", __func__);
+
+ return 0;
+}
+
+int mtk_isp_hw_release(struct mtk_cam_dev *cam)
+{
+ struct device *dev = cam->dev;
+ struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
+
+ isp_composer_hw_deinit(p1_dev);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+ rproc_shutdown(p1_dev->rproc_handle);
+
+ dev_dbg(dev, "%s done\n", __func__);
+
+ return 0;
+}
+
+void mtk_isp_req_enqueue(struct mtk_cam_dev *cam,
+ struct mtk_cam_dev_request *req)
+{
+ struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(cam->dev);
+
+ /* Accumulated frame sequence number */
+ req->frame_params.frame_seq_no = ++p1_dev->enqueued_frame_seq_no;
+
+ INIT_WORK(&req->frame_work, isp_tx_frame_worker);
+ queue_work(p1_dev->composer_wq, &req->frame_work);
+ dev_dbg(cam->dev, "enqueue fd:%s frame_seq_no:%d job cnt:%d\n",
+ req->req.debug_str, req->frame_params.frame_seq_no,
+ cam->running_job_count);
+}
+
+static void isp_irq_handle_sof(struct mtk_isp_p1_device *p1_dev,
+ unsigned int dequeued_frame_seq_no)
+{
+ dma_addr_t base_addr = p1_dev->composer_iova;
+ int composed_frame_seq_no = p1_dev->composed_frame_seq_no;
+ unsigned int addr_offset;
+
+ /* Send V4L2_EVENT_FRAME_SYNC event */
+ mtk_cam_dev_event_frame_sync(&p1_dev->cam_dev, dequeued_frame_seq_no);
+
+ p1_dev->sof_count += 1;
+ /* Save frame information */
+ p1_dev->dequeued_frame_seq_no = dequeued_frame_seq_no;
+ p1_dev->timestamp = ktime_get_ns();
+
+ /* Update CQ base address if needed */
+ if (composed_frame_seq_no <= dequeued_frame_seq_no) {
+ dev_dbg(p1_dev->dev,
+ "SOF_INT_ST, no update, cq_num:%d, frame_seq:%d\n",
+ composed_frame_seq_no, dequeued_frame_seq_no);
+ return;
+ }
+ addr_offset = MTK_ISP_CQ_ADDRESS_OFFSET *
+ (dequeued_frame_seq_no % MTK_ISP_CQ_BUFFER_COUNT);
+ writel(base_addr + addr_offset, p1_dev->regs + REG_CQ_THR0_BASEADDR);
+ dev_dbg(p1_dev->dev,
+ "SOF_INT_ST, update next, cq_num:%d, frame_seq:%d cq_addr:0x%x\n",
+ composed_frame_seq_no, dequeued_frame_seq_no, addr_offset);
+}
+
+static void isp_irq_handle_dma_err(struct mtk_isp_p1_device *p1_dev)
+{
+ u32 val;
+
+ dev_err(p1_dev->dev,
+ "IMGO:0x%x, RRZO:0x%x, AAO=0x%x, AFO=0x%x, LMVO=0x%x\n",
+ readl(p1_dev->regs + REG_IMGO_ERR_STAT),
+ readl(p1_dev->regs + REG_RRZO_ERR_STAT),
+ readl(p1_dev->regs + REG_AAO_ERR_STAT),
+ readl(p1_dev->regs + REG_AFO_ERR_STAT),
+ readl(p1_dev->regs + REG_LMVO_ERR_STAT));
+ dev_err(p1_dev->dev,
+ "LCSO=0x%x, PSO=0x%x, FLKO=0x%x, BPCI:0x%x, LSCI=0x%x\n",
+ readl(p1_dev->regs + REG_LCSO_ERR_STAT),
+ readl(p1_dev->regs + REG_PSO_ERR_STAT),
+ readl(p1_dev->regs + REG_FLKO_ERR_STAT),
+ readl(p1_dev->regs + REG_BPCI_ERR_STAT),
+ readl(p1_dev->regs + REG_LSCI_ERR_STAT));
+
+ /* Disable DMA error mask to avoid too much error log */
+ val = readl(p1_dev->regs + REG_CTL_RAW_INT_EN);
+ writel((val & (~DMA_ERR_INT_EN)), p1_dev->regs + REG_CTL_RAW_INT_EN);
+ dev_dbg(p1_dev->dev, "disable DMA error mask:0x%x\n", val);
+}
+
+static irqreturn_t isp_irq_cam(int irq, void *data)
+{
+ struct mtk_isp_p1_device *p1_dev = (struct mtk_isp_p1_device *)data;
+ struct device *dev = p1_dev->dev;
+ unsigned int dequeued_frame_seq_no;
+ unsigned int irq_status, err_status, dma_status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&p1_dev->spinlock_irq, flags);
+ irq_status = readl(p1_dev->regs + REG_CTL_RAW_INT_STAT);
+ err_status = irq_status & INT_ST_MASK_CAM_ERR;
+ dma_status = readl(p1_dev->regs + REG_CTL_RAW_INT2_STAT);
+ dequeued_frame_seq_no = readl(p1_dev->regs + REG_FRAME_SEQ_NUM);
+ spin_unlock_irqrestore(&p1_dev->spinlock_irq, flags);
+
+ /*
+ * In normal case, the next SOF ISR should come after HW PASS1 DONE ISR.
+ * If these two ISRs come together, print warning msg to hint.
+ */
+ if ((irq_status & SOF_INT_ST) && (irq_status & HW_PASS1_DON_ST))
+ dev_warn(dev, "sof_done block cnt:%d\n", p1_dev->sof_count);
+
+ /* De-queue frame */
+ if (irq_status & SW_PASS1_DON_ST) {
+ mtk_cam_dev_dequeue_req_frame(&p1_dev->cam_dev,
+ p1_dev->dequeued_frame_seq_no,
+ p1_dev->timestamp);
+ mtk_cam_dev_req_try_queue(&p1_dev->cam_dev);
+ }
+
+ /* Save frame info. & update CQ address for frame HW en-queue */
+ if (irq_status & SOF_INT_ST)
+ isp_irq_handle_sof(p1_dev, dequeued_frame_seq_no);
+
+ /* Check ISP error status */
+ if (err_status) {
+ dev_err(dev, "int_err:0x%x 0x%x\n", irq_status, err_status);
+ /* Show DMA errors in detail */
+ if (err_status & DMA_ERR_ST)
+ isp_irq_handle_dma_err(p1_dev);
+ }
+
+ dev_dbg(dev, "SOF:%d irq:0x%x, dma:0x%x, frame_num:%d\n",
+ p1_dev->sof_count, irq_status, dma_status,
+ dequeued_frame_seq_no);
+
+ return IRQ_HANDLED;
+}
+
+static int isp_setup_scp_rproc(struct mtk_isp_p1_device *p1_dev,
+ struct platform_device *pdev)
+{
+ phandle rproc_phandle;
+ struct device *dev = p1_dev->dev;
+ dma_addr_t addr;
+ void *ptr;
+ int ret;
+
+ p1_dev->scp_pdev = scp_get_pdev(pdev);
+ if (!p1_dev->scp_pdev) {
+ dev_err(dev, "failed to get scp device\n");
+ return -ENODEV;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "mediatek,scp",
+ &rproc_phandle);
+ if (ret) {
+ dev_err(dev, "failed to get rproc_phandle:%d\n", ret);
+ return -EINVAL;
+ }
+
+ p1_dev->rproc_handle = rproc_get_by_phandle(rproc_phandle);
+ dev_dbg(dev, "p1 rproc_phandle: 0x%pK\n", p1_dev->rproc_handle);
+ if (!p1_dev->rproc_handle) {
+ dev_err(dev, "failed to get rproc_handle\n");
+ return -EINVAL;
+ }
+ p1_dev->cam_dev.smem_dev = &p1_dev->scp_pdev->dev;
+
+ /*
+ * Allocate coherent reserved memory for SCP firmware usage.
+ * The size of SCP composer's memory is fixed to 0x200000
+ * for the requirement of firmware.
+ */
+ ptr = dma_alloc_coherent(p1_dev->cam_dev.smem_dev,
+ MTK_ISP_COMPOSER_MEM_SIZE, &addr, GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
+ p1_dev->composer_scp_addr = addr;
+ p1_dev->composer_virt_addr = ptr;
+ dev_dbg(dev, "scp addr:%pad va:%pK\n", &addr, ptr);
+
+ /*
+ * This reserved memory is also be used by ISP P1 HW.
+ * Need to get iova address for ISP P1 DMA.
+ */
+ addr = dma_map_resource(dev, addr, MTK_ISP_COMPOSER_MEM_SIZE,
+ DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC);
+ if (dma_mapping_error(dev, addr)) {
+ dev_err(dev, "failed to map scp iova\n");
+ ret = -ENOMEM;
+ goto fail_free_mem;
+ }
+ p1_dev->composer_iova = addr;
+ dev_dbg(dev, "scp iova addr:%pad\n", &addr);
+
+ return 0;
+
+fail_free_mem:
+ dma_free_coherent(p1_dev->cam_dev.smem_dev, MTK_ISP_COMPOSER_MEM_SIZE,
+ ptr, p1_dev->composer_scp_addr);
+ p1_dev->composer_scp_addr = 0;
+
+ return ret;
+}
+
+static int mtk_isp_pm_suspend(struct device *dev)
+{
+ struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
+ u32 val;
+ int ret;
+
+ dev_dbg(dev, "- %s\n", __func__);
+
+ if (pm_runtime_suspended(dev))
+ return 0;
+
+ /* Disable ISP's view finder and wait for TG idle */
+ dev_dbg(dev, "cam suspend, disable VF\n");
+ val = readl(p1_dev->regs + REG_TG_VF_CON);
+ writel(val & (~TG_VF_CON_VFDATA_EN), p1_dev->regs + REG_TG_VF_CON);
+ ret = readl_poll_timeout_atomic(p1_dev->regs + REG_TG_INTER_ST, val,
+ (val & TG_CS_MASK) == TG_IDLE_ST,
+ USEC_PER_MSEC, MTK_ISP_STOP_HW_TIMEOUT);
+ if (ret)
+ dev_warn(dev, "can't stop HW:%d:0x%x\n", ret, val);
+
+ /* Disable CMOS */
+ val = readl(p1_dev->regs + REG_TG_SEN_MODE);
+ writel(val & (~TG_SEN_MODE_CMOS_EN), p1_dev->regs + REG_TG_SEN_MODE);
+
+ /* Force ISP HW to idle */
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mtk_isp_pm_resume(struct device *dev)
+{
+ struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
+ u32 val;
+ int ret;
+
+ dev_dbg(dev, "- %s\n", __func__);
+
+ if (pm_runtime_suspended(dev))
+ return 0;
+
+ /* Force ISP HW to resume */
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ /* Enable CMOS */
+ dev_dbg(dev, "cam resume, enable CMOS/VF\n");
+ val = readl(p1_dev->regs + REG_TG_SEN_MODE);
+ writel(val | TG_SEN_MODE_CMOS_EN, p1_dev->regs + REG_TG_SEN_MODE);
+
+ /* Enable VF */
+ val = readl(p1_dev->regs + REG_TG_VF_CON);
+ writel(val | TG_VF_CON_VFDATA_EN, p1_dev->regs + REG_TG_VF_CON);
+
+ return 0;
+}
+
+static int mtk_isp_runtime_suspend(struct device *dev)
+{
+ struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "%s:disable clock\n", __func__);
+ clk_bulk_disable_unprepare(p1_dev->num_clks, p1_dev->clks);
+
+ return 0;
+}
+
+static int mtk_isp_runtime_resume(struct device *dev)
+{
+ struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
+ int ret;
+
+ dev_dbg(dev, "%s:enable clock\n", __func__);
+ ret = clk_bulk_prepare_enable(p1_dev->num_clks, p1_dev->clks);
+ if (ret) {
+ dev_err(dev, "failed to enable clock:%d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mtk_isp_probe(struct platform_device *pdev)
+{
+ /* List of clocks required by isp cam */
+ static const char * const clk_names[] = {
+ "camsys_cam_cgpdn", "camsys_camtg_cgpdn"
+ };
+ struct mtk_isp_p1_device *p1_dev;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ int irq, ret, i;
+
+ p1_dev = devm_kzalloc(dev, sizeof(*p1_dev), GFP_KERNEL);
+ if (!p1_dev)
+ return -ENOMEM;
+
+ p1_dev->dev = dev;
+ dev_set_drvdata(dev, p1_dev);
+
+ /*
+ * Now only support single CAM with CAM B.
+ * Get CAM B register base with CAM B index.
+ * Support multiple CAMs in future.
+ */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, MTK_ISP_CAM_ID_B);
+ p1_dev->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(p1_dev->regs)) {
+ dev_err(dev, "failed to map reister base\n");
+ return PTR_ERR(p1_dev->regs);
+ }
+ dev_dbg(dev, "cam, map_addr=0x%pK\n", p1_dev->regs);
+
+ /*
+ * The cam_sys unit only supports reg., but has no IRQ support.
+ * The reg. & IRQ index is shifted with 1 for CAM B in DTS.
+ */
+ irq = platform_get_irq(pdev, MTK_ISP_CAM_ID_B - 1);
+ if (!irq) {
+ dev_err(dev, "failed to get irq\n");
+ return -ENODEV;
+ }
+ ret = devm_request_irq(dev, irq, isp_irq_cam, 0, dev_name(dev),
+ p1_dev);
+ if (ret) {
+ dev_err(dev, "failed to request irq=%d\n", irq);
+ return ret;
+ }
+ dev_dbg(dev, "registered irq=%d\n", irq);
+ spin_lock_init(&p1_dev->spinlock_irq);
+
+ p1_dev->num_clks = ARRAY_SIZE(clk_names);
+ p1_dev->clks = devm_kcalloc(dev, p1_dev->num_clks,
+ sizeof(*p1_dev->clks), GFP_KERNEL);
+ if (!p1_dev->clks)
+ return -ENOMEM;
+
+ for (i = 0; i < p1_dev->num_clks; ++i)
+ p1_dev->clks[i].id = clk_names[i];
+
+ ret = devm_clk_bulk_get(dev, p1_dev->num_clks, p1_dev->clks);
+ if (ret) {
+ dev_err(dev, "failed to get isp cam clock:%d\n", ret);
+ return ret;
+ }
+
+ ret = isp_setup_scp_rproc(p1_dev, pdev);
+ if (ret)
+ return ret;
+
+ pm_runtime_set_autosuspend_delay(dev, 2 * MTK_ISP_STOP_HW_TIMEOUT);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_enable(dev);
+
+ /* Initialize the v4l2 common part */
+ ret = mtk_cam_dev_init(pdev, &p1_dev->cam_dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mtk_isp_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev);
+
+ mtk_cam_dev_cleanup(&p1_dev->cam_dev);
+ pm_runtime_dont_use_autosuspend(dev);
+ pm_runtime_disable(dev);
+ dma_unmap_page_attrs(dev, p1_dev->composer_iova,
+ MTK_ISP_COMPOSER_MEM_SIZE, DMA_BIDIRECTIONAL,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ dma_free_coherent(&p1_dev->scp_pdev->dev, MTK_ISP_COMPOSER_MEM_SIZE,
+ p1_dev->composer_virt_addr,
+ p1_dev->composer_scp_addr);
+ rproc_put(p1_dev->rproc_handle);
+
+ return 0;
+}
+
+static const struct dev_pm_ops mtk_isp_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(mtk_isp_pm_suspend, mtk_isp_pm_resume)
+ SET_RUNTIME_PM_OPS(mtk_isp_runtime_suspend, mtk_isp_runtime_resume,
+ NULL)
+};
+
+static const struct of_device_id mtk_isp_of_ids[] = {
+ {.compatible = "mediatek,mt8183-camisp",},
+ {}
+};
+MODULE_DEVICE_TABLE(of, mtk_isp_of_ids);
+
+static struct platform_driver mtk_isp_driver = {
+ .probe = mtk_isp_probe,
+ .remove = mtk_isp_remove,
+ .driver = {
+ .name = "mtk-cam-p1",
+ .of_match_table = of_match_ptr(mtk_isp_of_ids),
+ .pm = &mtk_isp_pm_ops,
+ }
+};
+
+module_platform_driver(mtk_isp_driver);
+
+MODULE_DESCRIPTION("Mediatek ISP P1 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.h b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.h
new file mode 100644
index 000000000000..52cd7e5f7e23
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MTK_CAM_HW_H__
+#define __MTK_CAM_HW_H__
+
+#include <linux/types.h>
+
+#include "mtk_cam.h"
+#include "mtk_cam-ipi.h"
+
+/*
+ * struct mtk_isp_p1_device - the Mediatek ISP P1 device information
+ *
+ * @dev: Pointer to device.
+ * @scp_pdev: Pointer to SCP platform device.
+ * @rproc_handle: Pointer to new remoteproc instance.
+ * @cam_dev: Embedded struct cam_dev
+ * @regs: Camera ISP HW base register address
+ * @num_clks: The number of driver's clocks
+ * @clks: The clock data array
+ * @spinlock_irq: Used to protect register read/write data
+ * @enqueued_frame_seq_no: Frame sequence number of enqueued frame
+ * @dequeued_frame_seq_no: Frame sequence number of dequeued frame
+ * @composed_frame_seq_no: Frame sequence number of composed frame
+ * @timestamp: Frame timestamp in ns
+ * @sof_count: SOF counter
+ * @composer_wq: The work queue for frame request composing
+ * @composer_scp_addr: SCP address of ISP composer memory
+ * @composer_iova: DMA address of ISP composer memory
+ * @virt_addr: Virtual address of ISP composer memory
+ *
+ */
+struct mtk_isp_p1_device {
+ struct device *dev;
+ struct platform_device *scp_pdev;
+ struct rproc *rproc_handle;
+ struct mtk_cam_dev cam_dev;
+ void __iomem *regs;
+ unsigned int num_clks;
+ struct clk_bulk_data *clks;
+ /* Used to protect register read/write data */
+ spinlock_t spinlock_irq;
+ unsigned int enqueued_frame_seq_no;
+ unsigned int dequeued_frame_seq_no;
+ unsigned int composed_frame_seq_no;
+ u64 timestamp;
+ u8 sof_count;
+ struct workqueue_struct *composer_wq;
+ dma_addr_t composer_scp_addr;
+ dma_addr_t composer_iova;
+ void *composer_virt_addr;
+};
+
+int mtk_isp_hw_init(struct mtk_cam_dev *cam_dev);
+int mtk_isp_hw_release(struct mtk_cam_dev *cam_dev);
+void mtk_isp_hw_config(struct mtk_cam_dev *cam_dev,
+ struct p1_config_param *config_param);
+void mtk_isp_stream(struct mtk_cam_dev *cam_dev, int on);
+void mtk_isp_req_enqueue(struct mtk_cam_dev *cam_dev,
+ struct mtk_cam_dev_request *req);
+
+#endif /* __MTK_CAM_HW_H__ */
diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h
new file mode 100644
index 000000000000..981b634dd91f
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h
@@ -0,0 +1,222 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MTK_CAM_IPI_H__
+#define __MTK_CAM_IPI_H__
+
+#include <linux/types.h>
+
+/*
+ * struct img_size - Image size information.
+ *
+ * @w: Image width, the unit is pixel
+ * @h: Image height, the unit is pixel
+ * @xsize: Bytes per line based on width.
+ * @stride: Bytes per line when changing line.
+ * Stride is based on xsize + HW constrain(byte align).
+ *
+ */
+struct img_size {
+ u32 w;
+ u32 h;
+ u32 xsize;
+ u32 stride;
+} __packed;
+
+/*
+ * struct p1_img_crop - image corp information
+ *
+ * @left: The left of crop area.
+ * @top: The top of crop area.
+ * @width: The width of crop area.
+ * @height: The height of crop area.
+ *
+ */
+struct p1_img_crop {
+ u32 left;
+ u32 top;
+ u32 width;
+ u32 height;
+} __packed;
+
+/*
+ * struct dma_buffer - DMA buffer address information
+ *
+ * @iova: DMA address for ISP DMA device
+ * @scp_addr: SCP address for external co-process unit
+ *
+ */
+struct dma_buffer {
+ u32 iova;
+ u32 scp_addr;
+} __packed;
+
+/*
+ * struct p1_img_output - ISP P1 image output information
+ *
+ * @buffer: DMA buffer address of image.
+ * @size: The image size configuration.
+ * @crop: The crop configuration.
+ * @pixel_bits: The bits per image pixel.
+ * @img_fmt: The image format.
+ *
+ */
+struct p1_img_output {
+ struct dma_buffer buffer;
+ struct img_size size;
+ struct p1_img_crop crop;
+ u8 pixel_bits;
+ u32 img_fmt;
+} __packed;
+
+/*
+ * struct cfg_in_param - Image input parameters structure.
+ * Normally, it comes from sensor information.
+ *
+ * @continuous: Indicate the sensor mode. Continuous or single shot.
+ * @subsample: Indicate to enables SOF subsample or not.
+ * @pixel_mode: Describe 1/2/4 pixels per clock cycle.
+ * @data_pattern: Describe input data pattern.
+ * @raw_pixel_id: Bayer sequence.
+ * @tg_fps: The fps rate of TG (time generator).
+ * @img_fmt: The image format of input source.
+ * @p1_img_crop: The crop configuration of input source.
+ *
+ */
+struct cfg_in_param {
+ u8 continuous;
+ u8 subsample;
+ u8 pixel_mode;
+ u8 data_pattern;
+ u8 raw_pixel_id;
+ u16 tg_fps;
+ u32 img_fmt;
+ struct p1_img_crop crop;
+} __packed;
+
+/*
+ * struct cfg_main_out_param - The image output parameters of main stream.
+ *
+ * @bypass: Indicate this device is enabled or disabled or not.
+ * @pure_raw: Indicate the image path control.
+ * True: pure raw
+ * False: processing raw
+ * @pure_raw_pack: Indicate the image is packed or not.
+ * True: packed mode
+ * False: unpacked mode
+ * @p1_img_output: The output image information.
+ *
+ */
+struct cfg_main_out_param {
+ u8 bypass;
+ u8 pure_raw;
+ u8 pure_raw_pack;
+ struct p1_img_output output;
+} __packed;
+
+/*
+ * struct cfg_resize_out_param - The image output parameters of
+ * packed out stream.
+ *
+ * @bypass: Indicate this device is enabled or disabled or not.
+ * @p1_img_output: The output image information.
+ *
+ */
+struct cfg_resize_out_param {
+ u8 bypass;
+ struct p1_img_output output;
+} __packed;
+
+/*
+ * struct p1_config_param - ISP P1 configuration parameters.
+ *
+ * @cfg_in_param: The Image input parameters.
+ * @cfg_main_param: The main output image parameters.
+ * @cfg_resize_out_param: The packed output image parameters.
+ * @enabled_dmas: The enabled DMA port information.
+ *
+ */
+struct p1_config_param {
+ struct cfg_in_param cfg_in_param;
+ struct cfg_main_out_param cfg_main_param;
+ struct cfg_resize_out_param cfg_resize_param;
+ u32 enabled_dmas;
+} __packed;
+
+/*
+ * struct P1_meta_frame - ISP P1 meta frame information.
+ *
+ * @enabled_dma: The enabled DMA port information.
+ * @vb_index: The VB2 index of meta buffer.
+ * @meta_addr: DMA buffer address of meta buffer.
+ *
+ */
+struct P1_meta_frame {
+ u32 enabled_dma;
+ u32 vb_index;
+ struct dma_buffer meta_addr;
+} __packed;
+
+/*
+ * struct isp_init_info - ISP P1 composer init information.
+ *
+ * @hw_module: The ISP Camera HW module ID.
+ * @cq_addr: The DMA address of composer memory.
+ *
+ */
+struct isp_init_info {
+ u8 hw_module;
+ struct dma_buffer cq_addr;
+} __packed;
+
+/*
+ * struct isp_ack_info - ISP P1 IPI command ack information.
+ *
+ * @cmd_id: The IPI command ID is acked.
+ * @frame_seq_no: The IPI frame sequence number is acked.
+ *
+ */
+struct isp_ack_info {
+ u8 cmd_id;
+ u32 frame_seq_no;
+} __packed;
+
+/*
+ * The IPI command enumeration.
+ */
+enum mtk_isp_scp_cmds {
+ ISP_CMD_INIT,
+ ISP_CMD_CONFIG,
+ ISP_CMD_STREAM,
+ ISP_CMD_DEINIT,
+ ISP_CMD_ACK,
+ ISP_CMD_FRAME_ACK,
+ ISP_CMD_RESERVED,
+};
+
+/*
+ * struct mtk_isp_scp_p1_cmd - ISP P1 IPI command strcture.
+ *
+ * @cmd_id: The IPI command ID.
+ * @init_param: The init formation for ISP_CMD_INIT.
+ * @config_param: The cmd configuration for ISP_CMD_CONFIG.
+ * @enabled_dmas: The meta configuration information for ISP_CMD_CONFIG_META.
+ * @is_stream_on: The stream information for ISP_CMD_STREAM.
+ * @ack_info: The cmd ack. information for ISP_CMD_ACK.
+ *
+ */
+struct mtk_isp_scp_p1_cmd {
+ u8 cmd_id;
+ union {
+ struct isp_init_info init_param;
+ struct p1_config_param config_param;
+ u32 enabled_dmas;
+ struct P1_meta_frame meta_frame;
+ u8 is_stream_on;
+ struct isp_ack_info ack_info;
+ };
+} __packed;
+
+#endif /* __MTK_CAM_IPI_H__ */
diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-regs.h b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-regs.h
new file mode 100644
index 000000000000..ab2277f45fa4
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-regs.h
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MTK_CAM_REGS_H__
+#define __MTK_CAM_REGS_H__
+
+/* ISP interrupt enable */
+#define REG_CTL_RAW_INT_EN 0x0020
+#define DMA_ERR_INT_EN BIT(29)
+
+/* ISP interrupt status */
+#define REG_CTL_RAW_INT_STAT 0x0024
+#define VS_INT_ST BIT(0)
+#define TG_ERR_ST BIT(4)
+#define TG_GBERR_ST BIT(5)
+#define CQ_CODE_ERR_ST BIT(6)
+#define CQ_APB_ERR_ST BIT(7)
+#define CQ_VS_ERR_ST BIT(8)
+#define HW_PASS1_DON_ST BIT(11)
+#define SOF_INT_ST BIT(12)
+#define AMX_ERR_ST BIT(15)
+#define RMX_ERR_ST BIT(16)
+#define BMX_ERR_ST BIT(17)
+#define RRZO_ERR_ST BIT(18)
+#define AFO_ERR_ST BIT(19)
+#define IMGO_ERR_ST BIT(20)
+#define AAO_ERR_ST BIT(21)
+#define PSO_ERR_ST BIT(22)
+#define LCSO_ERR_ST BIT(23)
+#define BNR_ERR_ST BIT(24)
+#define LSCI_ERR_ST BIT(25)
+#define DMA_ERR_ST BIT(29)
+#define SW_PASS1_DON_ST BIT(30)
+
+/* ISP interrupt 2 status */
+#define REG_CTL_RAW_INT2_STAT 0x0034
+#define AFO_DONE_ST BIT(5)
+#define AAO_DONE_ST BIT(7)
+
+/* Configures sensor mode */
+#define REG_TG_SEN_MODE 0x0230
+#define TG_SEN_MODE_CMOS_EN BIT(0)
+
+/* View finder mode control */
+#define REG_TG_VF_CON 0x0234
+#define TG_VF_CON_VFDATA_EN BIT(0)
+
+/* View finder mode control */
+#define REG_TG_INTER_ST 0x026c
+#define TG_CS_MASK 0x3f00
+#define TG_IDLE_ST BIT(8)
+
+/* IMGO error status register */
+#define REG_IMGO_ERR_STAT 0x1360
+/* RRZO error status register */
+#define REG_RRZO_ERR_STAT 0x1364
+/* AAO error status register */
+#define REG_AAO_ERR_STAT 0x1368
+/* AFO error status register */
+#define REG_AFO_ERR_STAT 0x136c
+/* LCSO error status register */
+#define REG_LCSO_ERR_STAT 0x1370
+/* BPCI error status register */
+#define REG_BPCI_ERR_STAT 0x137c
+/* LSCI error status register */
+#define REG_LSCI_ERR_STAT 0x1384
+/* LMVO error status register */
+#define REG_LMVO_ERR_STAT 0x1390
+/* FLKO error status register */
+#define REG_FLKO_ERR_STAT 0x1394
+/* PSO error status register */
+#define REG_PSO_ERR_STAT 0x13a0
+
+/* CQ0 base address */
+#define REG_CQ_THR0_BASEADDR 0x0198
+/* Frame sequence number */
+#define REG_FRAME_SEQ_NUM 0x13b8
+
+/* IRQ Error Mask */
+#define INT_ST_MASK_CAM_ERR ( \
+ TG_ERR_ST |\
+ TG_GBERR_ST |\
+ CQ_CODE_ERR_ST |\
+ CQ_APB_ERR_ST |\
+ CQ_VS_ERR_ST |\
+ BNR_ERR_ST |\
+ RMX_ERR_ST |\
+ BMX_ERR_ST |\
+ BNR_ERR_ST |\
+ LSCI_ERR_ST |\
+ DMA_ERR_ST)
+
+#endif /* __MTK_CAM_REGS_H__ */
diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.c b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.c
new file mode 100644
index 000000000000..229eb7425c0e
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.c
@@ -0,0 +1,2066 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2019 MediaTek Inc.
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/of_platform.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/videodev2.h>
+#include <media/media-entity.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "mtk_cam.h"
+#include "mtk_cam-hw.h"
+
+#define R_IMGO BIT(0)
+#define R_RRZO BIT(1)
+#define R_AAO BIT(3)
+#define R_AFO BIT(4)
+#define R_LCSO BIT(5)
+#define R_LMVO BIT(7)
+#define R_FLKO BIT(8)
+#define R_PSO BIT(10)
+
+#define MTK_ISP_ONE_PIXEL_MODE 1
+#define MTK_ISP_MIN_RESIZE_RATIO 6
+#define MTK_ISP_MAX_RUNNING_JOBS 3
+
+#define MTK_CAM_CIO_PAD_SRC 4
+#define MTK_CAM_CIO_PAD_SINK 11
+
+static inline struct mtk_cam_video_device *
+file_to_mtk_cam_node(struct file *__file)
+{
+ return container_of(video_devdata(__file),
+ struct mtk_cam_video_device, vdev);
+}
+
+static inline struct mtk_cam_video_device *
+mtk_cam_vbq_to_vdev(struct vb2_queue *__vq)
+{
+ return container_of(__vq, struct mtk_cam_video_device, vbq);
+}
+
+static inline struct mtk_cam_dev_request *
+mtk_cam_req_to_dev_req(struct media_request *__req)
+{
+ return container_of(__req, struct mtk_cam_dev_request, req);
+}
+
+static inline struct mtk_cam_dev_buffer *
+mtk_cam_vb2_buf_to_dev_buf(struct vb2_buffer *__vb)
+{
+ return container_of(__vb, struct mtk_cam_dev_buffer, vbb.vb2_buf);
+}
+
+static void mtk_cam_dev_job_done(struct mtk_cam_dev *cam,
+ struct mtk_cam_dev_request *req,
+ u64 tstamp_soe, enum vb2_buffer_state state)
+{
+ struct media_request_object *obj, *obj_prev;
+ unsigned long flags;
+ u64 tstamp_eof = ktime_get_ns();
+
+ if (!cam->streaming)
+ return;
+
+ dev_dbg(cam->dev, "job done request:%s frame_seq:%d state:%d\n",
+ req->req.debug_str, req->frame_params.frame_seq_no, state);
+
+ list_for_each_entry_safe(obj, obj_prev, &req->req.objects, list) {
+ struct vb2_buffer *vb;
+ struct mtk_cam_dev_buffer *buf;
+ struct mtk_cam_video_device *node;
+
+ if (!vb2_request_object_is_buffer(obj))
+ continue;
+ vb = container_of(obj, struct vb2_buffer, req_obj);
+ buf = mtk_cam_vb2_buf_to_dev_buf(vb);
+ node = mtk_cam_vbq_to_vdev(vb->vb2_queue);
+ spin_lock_irqsave(&node->buf_list_lock, flags);
+ list_del(&buf->list);
+ spin_unlock_irqrestore(&node->buf_list_lock, flags);
+ buf->vbb.sequence = req->frame_params.frame_seq_no;
+ if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
+ vb->timestamp = tstamp_eof;
+ else
+ vb->timestamp = tstamp_soe;
+ vb2_buffer_done(&buf->vbb.vb2_buf, state);
+ }
+}
+
+void mtk_cam_dev_dequeue_req_frame(struct mtk_cam_dev *cam,
+ unsigned int frame_seq_no, u64 tstamp)
+{
+ struct mtk_cam_dev_request *req, *req_prev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cam->running_job_lock, flags);
+ list_for_each_entry_safe(req, req_prev, &cam->running_job_list, list) {
+ dev_dbg(cam->dev, "frame_seq:%d, de-queue frame_seq:%d\n",
+ req->frame_params.frame_seq_no, frame_seq_no);
+
+ /* Match by the en-queued request number */
+ if (req->frame_params.frame_seq_no == frame_seq_no) {
+ cam->running_job_count--;
+ /* Pass to user space */
+ mtk_cam_dev_job_done(cam, req, tstamp,
+ VB2_BUF_STATE_DONE);
+ list_del(&req->list);
+ break;
+ } else if (req->frame_params.frame_seq_no < frame_seq_no) {
+ cam->running_job_count--;
+ /* Pass to user space for frame drop */
+ mtk_cam_dev_job_done(cam, req, tstamp,
+ VB2_BUF_STATE_ERROR);
+ dev_warn(cam->dev, "frame_seq:%d drop\n",
+ req->frame_params.frame_seq_no);
+ list_del(&req->list);
+ } else {
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&cam->running_job_lock, flags);
+}
+
+static void mtk_cam_dev_req_cleanup(struct mtk_cam_dev *cam)
+{
+ struct mtk_cam_dev_request *req, *req_prev;
+ unsigned long flags;
+
+ dev_dbg(cam->dev, "%s\n", __func__);
+
+ spin_lock_irqsave(&cam->pending_job_lock, flags);
+ list_for_each_entry_safe(req, req_prev, &cam->pending_job_list, list)
+ list_del(&req->list);
+ spin_unlock_irqrestore(&cam->pending_job_lock, flags);
+
+ spin_lock_irqsave(&cam->running_job_lock, flags);
+ list_for_each_entry_safe(req, req_prev, &cam->running_job_list, list)
+ list_del(&req->list);
+ spin_unlock_irqrestore(&cam->running_job_lock, flags);
+}
+
+void mtk_cam_dev_req_try_queue(struct mtk_cam_dev *cam)
+{
+ struct mtk_cam_dev_request *req, *req_prev;
+ unsigned long flags;
+
+ if (!cam->streaming) {
+ dev_dbg(cam->dev, "stream is off\n");
+ return;
+ }
+
+ spin_lock_irqsave(&cam->pending_job_lock, flags);
+ spin_lock_irqsave(&cam->running_job_lock, flags);
+ list_for_each_entry_safe(req, req_prev, &cam->pending_job_list, list) {
+ if (cam->running_job_count >= MTK_ISP_MAX_RUNNING_JOBS) {
+ dev_dbg(cam->dev, "jobs are full\n");
+ break;
+ }
+ cam->running_job_count++;
+ list_del(&req->list);
+ list_add_tail(&req->list, &cam->running_job_list);
+ mtk_isp_req_enqueue(cam, req);
+ }
+ spin_unlock_irqrestore(&cam->running_job_lock, flags);
+ spin_unlock_irqrestore(&cam->pending_job_lock, flags);
+}
+
+static struct media_request *mtk_cam_req_alloc(struct media_device *mdev)
+{
+ struct mtk_cam_dev_request *cam_dev_req;
+
+ cam_dev_req = kzalloc(sizeof(*cam_dev_req), GFP_KERNEL);
+
+ return &cam_dev_req->req;
+}
+
+static void mtk_cam_req_free(struct media_request *req)
+{
+ struct mtk_cam_dev_request *cam_dev_req = mtk_cam_req_to_dev_req(req);
+
+ kfree(cam_dev_req);
+}
+
+static void mtk_cam_req_queue(struct media_request *req)
+{
+ struct mtk_cam_dev_request *cam_req = mtk_cam_req_to_dev_req(req);
+ struct mtk_cam_dev *cam = container_of(req->mdev, struct mtk_cam_dev,
+ media_dev);
+ unsigned long flags;
+
+ cam_req->buf_count = vb2_request_buffer_cnt(req);
+
+ /* add to pending job list */
+ spin_lock_irqsave(&cam->pending_job_lock, flags);
+ list_add_tail(&cam_req->list, &cam->pending_job_list);
+ spin_unlock_irqrestore(&cam->pending_job_lock, flags);
+
+ vb2_request_queue(req);
+}
+
+static unsigned int get_pixel_bits(unsigned int pix_fmt)
+{
+ switch (pix_fmt) {
+ case V4L2_PIX_FMT_MTISP_SBGGR8:
+ case V4L2_PIX_FMT_MTISP_SGBRG8:
+ case V4L2_PIX_FMT_MTISP_SGRBG8:
+ case V4L2_PIX_FMT_MTISP_SRGGB8:
+ case V4L2_PIX_FMT_MTISP_SBGGR8F:
+ case V4L2_PIX_FMT_MTISP_SGBRG8F:
+ case V4L2_PIX_FMT_MTISP_SGRBG8F:
+ case V4L2_PIX_FMT_MTISP_SRGGB8F:
+ return 8;
+ case V4L2_PIX_FMT_MTISP_SBGGR10:
+ case V4L2_PIX_FMT_MTISP_SGBRG10:
+ case V4L2_PIX_FMT_MTISP_SGRBG10:
+ case V4L2_PIX_FMT_MTISP_SRGGB10:
+ case V4L2_PIX_FMT_MTISP_SBGGR10F:
+ case V4L2_PIX_FMT_MTISP_SGBRG10F:
+ case V4L2_PIX_FMT_MTISP_SGRBG10F:
+ case V4L2_PIX_FMT_MTISP_SRGGB10F:
+ return 10;
+ case V4L2_PIX_FMT_MTISP_SBGGR12:
+ case V4L2_PIX_FMT_MTISP_SGBRG12:
+ case V4L2_PIX_FMT_MTISP_SGRBG12:
+ case V4L2_PIX_FMT_MTISP_SRGGB12:
+ case V4L2_PIX_FMT_MTISP_SBGGR12F:
+ case V4L2_PIX_FMT_MTISP_SGBRG12F:
+ case V4L2_PIX_FMT_MTISP_SGRBG12F:
+ case V4L2_PIX_FMT_MTISP_SRGGB12F:
+ return 12;
+ case V4L2_PIX_FMT_MTISP_SBGGR14:
+ case V4L2_PIX_FMT_MTISP_SGBRG14:
+ case V4L2_PIX_FMT_MTISP_SGRBG14:
+ case V4L2_PIX_FMT_MTISP_SRGGB14:
+ case V4L2_PIX_FMT_MTISP_SBGGR14F:
+ case V4L2_PIX_FMT_MTISP_SGBRG14F:
+ case V4L2_PIX_FMT_MTISP_SGRBG14F:
+ case V4L2_PIX_FMT_MTISP_SRGGB14F:
+ return 14;
+ default:
+ return 0;
+ }
+}
+
+static void cal_image_pix_mp(struct mtk_cam_dev *cam, unsigned int node_id,
+ struct v4l2_pix_format_mplane *mp)
+{
+ unsigned int bpl, ppl;
+ unsigned int pixel_bits = get_pixel_bits(mp->pixelformat);
+ unsigned int width = mp->width;
+
+ bpl = 0;
+ if (node_id == MTK_CAM_P1_MAIN_STREAM_OUT) {
+ /* Bayer encoding format & 2 bytes alignment */
+ bpl = ALIGN(DIV_ROUND_UP(width * pixel_bits, 8), 2);
+ } else if (node_id == MTK_CAM_P1_PACKED_BIN_OUT) {
+ /*
+ * The FULL-G encoding format
+ * 1 G component per pixel
+ * 1 R component per 4 pixel
+ * 1 B component per 4 pixel
+ * Total 4G/1R/1B in 4 pixel (pixel per line:ppl)
+ */
+ ppl = DIV_ROUND_UP(width * 6, 4);
+ bpl = DIV_ROUND_UP(ppl * pixel_bits, 8);
+
+ /* 4 bytes alignment for 10 bit & others are 8 bytes */
+ if (pixel_bits == 10)
+ bpl = ALIGN(bpl, 4);
+ else
+ bpl = ALIGN(bpl, 8);
+ }
+ /*
+ * This image output buffer will be input buffer of MTK CAM DIP HW
+ * For MTK CAM DIP HW constrained, it needs 4 bytes alignment
+ */
+ bpl = ALIGN(bpl, 4);
+
+ mp->plane_fmt[0].bytesperline = bpl;
+ mp->plane_fmt[0].sizeimage = bpl * mp->height;
+
+ dev_dbg(cam->dev, "node:%d width:%d bytesperline:%d sizeimage:%d\n",
+ node_id, width, bpl, mp->plane_fmt[0].sizeimage);
+}
+
+static const struct v4l2_format *
+mtk_cam_dev_find_fmt(struct mtk_cam_dev_node_desc *desc, u32 format)
+{
+ int i;
+ const struct v4l2_format *dev_fmt;
+
+ for (i = 0; i < desc->num_fmts; i++) {
+ dev_fmt = &desc->fmts[i];
+ if (dev_fmt->fmt.pix_mp.pixelformat == format)
+ return dev_fmt;
+ }
+
+ return NULL;
+}
+
+/* Get the default format setting */
+static void
+mtk_cam_dev_load_default_fmt(struct mtk_cam_dev *cam,
+ struct mtk_cam_dev_node_desc *queue_desc,
+ struct v4l2_format *dest)
+{
+ const struct v4l2_format *default_fmt =
+ &queue_desc->fmts[queue_desc->default_fmt_idx];
+
+ dest->type = queue_desc->buf_type;
+
+ /* Configure default format based on node type */
+ if (!queue_desc->image) {
+ dest->fmt.meta.dataformat = default_fmt->fmt.meta.dataformat;
+ dest->fmt.meta.buffersize = default_fmt->fmt.meta.buffersize;
+ return;
+ }
+
+ dest->fmt.pix_mp.pixelformat = default_fmt->fmt.pix_mp.pixelformat;
+ dest->fmt.pix_mp.width = default_fmt->fmt.pix_mp.width;
+ dest->fmt.pix_mp.height = default_fmt->fmt.pix_mp.height;
+ /* bytesperline & sizeimage calculation */
+ cal_image_pix_mp(cam, queue_desc->id, &dest->fmt.pix_mp);
+ dest->fmt.pix_mp.num_planes = 1;
+
+ dest->fmt.pix_mp.colorspace = V4L2_COLORSPACE_SRGB;
+ dest->fmt.pix_mp.field = V4L2_FIELD_NONE;
+ dest->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ dest->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
+ dest->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_SRGB;
+}
+
+/* Utility functions */
+static unsigned int get_sensor_pixel_id(unsigned int fmt)
+{
+ switch (fmt) {
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
+ case MEDIA_BUS_FMT_SBGGR12_1X12:
+ case MEDIA_BUS_FMT_SBGGR14_1X14:
+ return MTK_CAM_RAW_PXL_ID_B;
+ case MEDIA_BUS_FMT_SGBRG8_1X8:
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
+ case MEDIA_BUS_FMT_SGBRG12_1X12:
+ case MEDIA_BUS_FMT_SGBRG14_1X14:
+ return MTK_CAM_RAW_PXL_ID_GB;
+ case MEDIA_BUS_FMT_SGRBG8_1X8:
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
+ case MEDIA_BUS_FMT_SGRBG12_1X12:
+ case MEDIA_BUS_FMT_SGRBG14_1X14:
+ return MTK_CAM_RAW_PXL_ID_GR;
+ case MEDIA_BUS_FMT_SRGGB8_1X8:
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
+ case MEDIA_BUS_FMT_SRGGB12_1X12:
+ case MEDIA_BUS_FMT_SRGGB14_1X14:
+ return MTK_CAM_RAW_PXL_ID_R;
+ default:
+ return MTK_CAM_RAW_PXL_ID_UNKNOWN;
+ }
+}
+
+static unsigned int get_sensor_fmt(unsigned int fmt)
+{
+ switch (fmt) {
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
+ case MEDIA_BUS_FMT_SGBRG8_1X8:
+ case MEDIA_BUS_FMT_SGRBG8_1X8:
+ case MEDIA_BUS_FMT_SRGGB8_1X8:
+ return MTK_CAM_IMG_FMT_BAYER8;
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
+ return MTK_CAM_IMG_FMT_BAYER10;
+ case MEDIA_BUS_FMT_SBGGR12_1X12:
+ case MEDIA_BUS_FMT_SGBRG12_1X12:
+ case MEDIA_BUS_FMT_SGRBG12_1X12:
+ case MEDIA_BUS_FMT_SRGGB12_1X12:
+ return MTK_CAM_IMG_FMT_BAYER12;
+ case MEDIA_BUS_FMT_SBGGR14_1X14:
+ case MEDIA_BUS_FMT_SGBRG14_1X14:
+ case MEDIA_BUS_FMT_SGRBG14_1X14:
+ case MEDIA_BUS_FMT_SRGGB14_1X14:
+ return MTK_CAM_IMG_FMT_BAYER14;
+ default:
+ return MTK_CAM_IMG_FMT_UNKNOWN;
+ }
+}
+
+static unsigned int get_img_fmt(unsigned int fourcc)
+{
+ switch (fourcc) {
+ case V4L2_PIX_FMT_MTISP_SBGGR8:
+ case V4L2_PIX_FMT_MTISP_SGBRG8:
+ case V4L2_PIX_FMT_MTISP_SGRBG8:
+ case V4L2_PIX_FMT_MTISP_SRGGB8:
+ return MTK_CAM_IMG_FMT_BAYER8;
+ case V4L2_PIX_FMT_MTISP_SBGGR8F:
+ case V4L2_PIX_FMT_MTISP_SGBRG8F:
+ case V4L2_PIX_FMT_MTISP_SGRBG8F:
+ case V4L2_PIX_FMT_MTISP_SRGGB8F:
+ return MTK_CAM_IMG_FMT_FG_BAYER8;
+ case V4L2_PIX_FMT_MTISP_SBGGR10:
+ case V4L2_PIX_FMT_MTISP_SGBRG10:
+ case V4L2_PIX_FMT_MTISP_SGRBG10:
+ case V4L2_PIX_FMT_MTISP_SRGGB10:
+ return MTK_CAM_IMG_FMT_BAYER10;
+ case V4L2_PIX_FMT_MTISP_SBGGR10F:
+ case V4L2_PIX_FMT_MTISP_SGBRG10F:
+ case V4L2_PIX_FMT_MTISP_SGRBG10F:
+ case V4L2_PIX_FMT_MTISP_SRGGB10F:
+ return MTK_CAM_IMG_FMT_FG_BAYER10;
+ case V4L2_PIX_FMT_MTISP_SBGGR12:
+ case V4L2_PIX_FMT_MTISP_SGBRG12:
+ case V4L2_PIX_FMT_MTISP_SGRBG12:
+ case V4L2_PIX_FMT_MTISP_SRGGB12:
+ return MTK_CAM_IMG_FMT_BAYER12;
+ case V4L2_PIX_FMT_MTISP_SBGGR12F:
+ case V4L2_PIX_FMT_MTISP_SGBRG12F:
+ case V4L2_PIX_FMT_MTISP_SGRBG12F:
+ case V4L2_PIX_FMT_MTISP_SRGGB12F:
+ return MTK_CAM_IMG_FMT_FG_BAYER12;
+ case V4L2_PIX_FMT_MTISP_SBGGR14:
+ case V4L2_PIX_FMT_MTISP_SGBRG14:
+ case V4L2_PIX_FMT_MTISP_SGRBG14:
+ case V4L2_PIX_FMT_MTISP_SRGGB14:
+ return MTK_CAM_IMG_FMT_BAYER14;
+ case V4L2_PIX_FMT_MTISP_SBGGR14F:
+ case V4L2_PIX_FMT_MTISP_SGBRG14F:
+ case V4L2_PIX_FMT_MTISP_SGRBG14F:
+ case V4L2_PIX_FMT_MTISP_SRGGB14F:
+ return MTK_CAM_IMG_FMT_FG_BAYER14;
+ default:
+ return MTK_CAM_IMG_FMT_UNKNOWN;
+ }
+}
+
+static int config_img_fmt(struct mtk_cam_dev *cam, unsigned int node_id,
+ struct p1_img_output *out_fmt, int sd_width,
+ int sd_height)
+{
+ const struct v4l2_format *cfg_fmt = &cam->vdev_nodes[node_id].vdev_fmt;
+
+ /* Check output & input image size dimension */
+ if (cfg_fmt->fmt.pix_mp.width > sd_width ||
+ cfg_fmt->fmt.pix_mp.height > sd_height) {
+ dev_err(cam->dev, "node:%d cfg size is larger than sensor\n",
+ node_id);
+ return -EINVAL;
+ }
+
+ /* Check resize ratio for resize out stream due to HW constraint */
+ if (((cfg_fmt->fmt.pix_mp.width * 100 / sd_width) <
+ MTK_ISP_MIN_RESIZE_RATIO) ||
+ ((cfg_fmt->fmt.pix_mp.height * 100 / sd_height) <
+ MTK_ISP_MIN_RESIZE_RATIO)) {
+ dev_err(cam->dev, "node:%d resize ratio is less than %d%%\n",
+ node_id, MTK_ISP_MIN_RESIZE_RATIO);
+ return -EINVAL;
+ }
+
+ out_fmt->img_fmt = get_img_fmt(cfg_fmt->fmt.pix_mp.pixelformat);
+ out_fmt->pixel_bits = get_pixel_bits(cfg_fmt->fmt.pix_mp.pixelformat);
+ if (out_fmt->img_fmt == MTK_CAM_IMG_FMT_UNKNOWN ||
+ !out_fmt->pixel_bits) {
+ dev_err(cam->dev, "node:%d unknown pixel fmt:%d\n",
+ node_id, cfg_fmt->fmt.pix_mp.pixelformat);
+ return -EINVAL;
+ }
+ dev_dbg(cam->dev, "node:%d pixel_bits:%d img_fmt:0x%x\n",
+ node_id, out_fmt->pixel_bits, out_fmt->img_fmt);
+
+ out_fmt->size.w = cfg_fmt->fmt.pix_mp.width;
+ out_fmt->size.h = cfg_fmt->fmt.pix_mp.height;
+ out_fmt->size.stride = cfg_fmt->fmt.pix_mp.plane_fmt[0].bytesperline;
+ out_fmt->size.xsize = cfg_fmt->fmt.pix_mp.plane_fmt[0].bytesperline;
+
+ out_fmt->crop.left = 0;
+ out_fmt->crop.top = 0;
+ out_fmt->crop.width = sd_width;
+ out_fmt->crop.height = sd_height;
+
+ dev_dbg(cam->dev,
+ "node:%d size=%0dx%0d, stride:%d, xsize:%d, crop=%0dx%0d\n",
+ node_id, out_fmt->size.w, out_fmt->size.h,
+ out_fmt->size.stride, out_fmt->size.xsize,
+ out_fmt->crop.width, out_fmt->crop.height);
+
+ return 0;
+}
+
+static void mtk_cam_dev_init_stream(struct mtk_cam_dev *cam)
+{
+ int i;
+
+ cam->enabled_count = 0;
+ cam->enabled_dmas = 0;
+ cam->stream_count = 0;
+ cam->running_job_count = 0;
+
+ /* Get the enabled meta DMA ports */
+ for (i = 0; i < MTK_CAM_P1_TOTAL_NODES; i++) {
+ if (!cam->vdev_nodes[i].enabled)
+ continue;
+ cam->enabled_count++;
+ cam->enabled_dmas |= cam->vdev_nodes[i].desc.dma_port;
+ }
+
+ dev_dbg(cam->dev, "%s:%d:0x%x\n", __func__, cam->enabled_count,
+ cam->enabled_dmas);
+}
+
+static int mtk_cam_dev_isp_config(struct mtk_cam_dev *cam)
+{
+ struct device *dev = cam->dev;
+ struct p1_config_param config_param;
+ struct cfg_in_param *cfg_in_param;
+ struct v4l2_subdev_format sd_fmt;
+ int sd_width, sd_height, sd_code;
+ unsigned int enabled_dma_ports = cam->enabled_dmas;
+ int ret;
+
+ /* Get sensor format configuration */
+ sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ ret = v4l2_subdev_call(cam->sensor, pad, get_fmt, NULL, &sd_fmt);
+ if (ret) {
+ dev_dbg(dev, "sensor g_fmt failed:%d\n", ret);
+ return ret;
+ }
+ sd_width = sd_fmt.format.width;
+ sd_height = sd_fmt.format.height;
+ sd_code = sd_fmt.format.code;
+ dev_dbg(dev, "sd fmt w*h=%d*%d, code=0x%x\n", sd_width, sd_height,
+ sd_code);
+
+ memset(&config_param, 0, sizeof(config_param));
+
+ /* Update cfg_in_param */
+ cfg_in_param = &config_param.cfg_in_param;
+ cfg_in_param->continuous = true;
+ /* Fix to one pixel mode in default */
+ cfg_in_param->pixel_mode = MTK_ISP_ONE_PIXEL_MODE;
+ cfg_in_param->crop.width = sd_width;
+ cfg_in_param->crop.height = sd_height;
+ cfg_in_param->raw_pixel_id = get_sensor_pixel_id(sd_code);
+ cfg_in_param->img_fmt = get_sensor_fmt(sd_code);
+ if (cfg_in_param->img_fmt == MTK_CAM_IMG_FMT_UNKNOWN ||
+ cfg_in_param->raw_pixel_id == MTK_CAM_RAW_PXL_ID_UNKNOWN) {
+ dev_err(dev, "unknown sd code:%d\n", sd_code);
+ return -EINVAL;
+ }
+
+ /* Update cfg_main_param */
+ config_param.cfg_main_param.pure_raw = true;
+ config_param.cfg_main_param.pure_raw_pack = true;
+ ret = config_img_fmt(cam, MTK_CAM_P1_MAIN_STREAM_OUT,
+ &config_param.cfg_main_param.output,
+ sd_width, sd_height);
+ if (ret)
+ return ret;
+
+ /* Update cfg_resize_param */
+ if (enabled_dma_ports & R_RRZO) {
+ ret = config_img_fmt(cam, MTK_CAM_P1_PACKED_BIN_OUT,
+ &config_param.cfg_resize_param.output,
+ sd_width, sd_height);
+ if (ret)
+ return ret;
+ } else {
+ config_param.cfg_resize_param.bypass = true;
+ }
+
+ /* Update enabled_dmas */
+ config_param.enabled_dmas = enabled_dma_ports;
+ mtk_isp_hw_config(cam, &config_param);
+ dev_dbg(dev, "%s done\n", __func__);
+
+ return 0;
+}
+
+void mtk_cam_dev_event_frame_sync(struct mtk_cam_dev *cam,
+ unsigned int frame_seq_no)
+{
+ struct v4l2_event event = {
+ .type = V4L2_EVENT_FRAME_SYNC,
+ .u.frame_sync.frame_sequence = frame_seq_no,
+ };
+
+ v4l2_event_queue(cam->subdev.devnode, &event);
+}
+
+static struct v4l2_subdev *
+mtk_cam_cio_get_active_sensor(struct mtk_cam_dev *cam)
+{
+ struct media_device *mdev = cam->seninf->entity.graph_obj.mdev;
+ struct device *dev = cam->dev;
+ struct media_entity *entity;
+ struct v4l2_subdev *sensor;
+
+ sensor = NULL;
+ media_device_for_each_entity(entity, mdev) {
+ dev_dbg(dev, "media entity: %s:0x%x:%d\n",
+ entity->name, entity->function, entity->stream_count);
+ if (entity->function == MEDIA_ENT_F_CAM_SENSOR &&
+ entity->stream_count) {
+ sensor = media_entity_to_v4l2_subdev(entity);
+ dev_dbg(dev, "sensor found: %s\n", entity->name);
+ break;
+ }
+ }
+
+ if (!sensor)
+ dev_err(dev, "no seninf connected\n");
+
+ return sensor;
+}
+
+static int mtk_cam_cio_stream_on(struct mtk_cam_dev *cam)
+{
+ struct device *dev = cam->dev;
+ int ret;
+
+ if (!cam->seninf) {
+ dev_err(dev, "no seninf connected\n");
+ return -ENODEV;
+ }
+
+ /* Get active sensor from graph topology */
+ cam->sensor = mtk_cam_cio_get_active_sensor(cam);
+ if (!cam->sensor)
+ return -ENODEV;
+
+ /* Seninf must stream on first */
+ ret = v4l2_subdev_call(cam->seninf, video, s_stream, 1);
+ if (ret) {
+ dev_err(dev, "failed to stream on %s:%d\n",
+ cam->seninf->entity.name, ret);
+ return ret;
+ }
+
+ ret = v4l2_subdev_call(cam->sensor, video, s_stream, 1);
+ if (ret) {
+ dev_err(dev, "failed to stream on %s:%d\n",
+ cam->sensor->entity.name, ret);
+ goto fail_seninf_off;
+ }
+
+ ret = mtk_cam_dev_isp_config(cam);
+ if (ret)
+ goto fail_sensor_off;
+
+ cam->streaming = true;
+ mtk_isp_stream(cam, 1);
+ mtk_cam_dev_req_try_queue(cam);
+ dev_dbg(dev, "streamed on Pass 1\n");
+
+ return 0;
+
+fail_sensor_off:
+ v4l2_subdev_call(cam->sensor, video, s_stream, 0);
+fail_seninf_off:
+ v4l2_subdev_call(cam->seninf, video, s_stream, 0);
+
+ return ret;
+}
+
+static int mtk_cam_cio_stream_off(struct mtk_cam_dev *cam)
+{
+ struct device *dev = cam->dev;
+ int ret;
+
+ ret = v4l2_subdev_call(cam->sensor, video, s_stream, 0);
+ if (ret) {
+ dev_err(dev, "failed to stream off %s:%d\n",
+ cam->sensor->entity.name, ret);
+ return -EPERM;
+ }
+
+ ret = v4l2_subdev_call(cam->seninf, video, s_stream, 0);
+ if (ret) {
+ dev_err(dev, "failed to stream off %s:%d\n",
+ cam->seninf->entity.name, ret);
+ return -EPERM;
+ }
+
+ cam->streaming = false;
+ mtk_isp_stream(cam, 0);
+ mtk_isp_hw_release(cam);
+
+ dev_dbg(dev, "streamed off Pass 1\n");
+
+ return 0;
+}
+
+static int mtk_cam_sd_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct mtk_cam_dev *cam = container_of(sd, struct mtk_cam_dev, subdev);
+
+ if (enable) {
+ /* Align vb2_core_streamon design */
+ if (cam->streaming) {
+ dev_warn(cam->dev, "already streaming on\n");
+ return 0;
+ }
+ return mtk_cam_cio_stream_on(cam);
+ }
+
+ if (!cam->streaming) {
+ dev_warn(cam->dev, "already streaming off\n");
+ return 0;
+ }
+ return mtk_cam_cio_stream_off(cam);
+}
+
+static int mtk_cam_sd_subscribe_event(struct v4l2_subdev *subdev,
+ struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ switch (sub->type) {
+ case V4L2_EVENT_FRAME_SYNC:
+ return v4l2_event_subscribe(fh, sub, 0, NULL);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mtk_cam_media_link_setup(struct media_entity *entity,
+ const struct media_pad *local,
+ const struct media_pad *remote, u32 flags)
+{
+ struct mtk_cam_dev *cam =
+ container_of(entity, struct mtk_cam_dev, subdev.entity);
+ u32 pad = local->index;
+
+ dev_dbg(cam->dev, "%s: %d->%d flags:0x%x\n",
+ __func__, pad, remote->index, flags);
+
+ /*
+ * The video nodes exposed by the driver have pads indexes
+ * from 0 to MTK_CAM_P1_TOTAL_NODES - 1.
+ */
+ if (pad < MTK_CAM_P1_TOTAL_NODES)
+ cam->vdev_nodes[pad].enabled =
+ !!(flags & MEDIA_LNK_FL_ENABLED);
+
+ return 0;
+}
+
+static void mtk_cam_vb2_buf_queue(struct vb2_buffer *vb)
+{
+ struct mtk_cam_dev *cam = vb2_get_drv_priv(vb->vb2_queue);
+ struct mtk_cam_dev_buffer *buf = mtk_cam_vb2_buf_to_dev_buf(vb);
+ struct mtk_cam_dev_request *req = mtk_cam_req_to_dev_req(vb->request);
+ struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vb->vb2_queue);
+ struct device *dev = cam->dev;
+ unsigned long flags;
+
+ dev_dbg(dev, "%s: node:%d fd:%d idx:%d\n", __func__,
+ node->id, buf->vbb.request_fd, buf->vbb.vb2_buf.index);
+
+ /* added the buffer into the tracking list */
+ spin_lock_irqsave(&node->buf_list_lock, flags);
+ list_add_tail(&buf->list, &node->buf_list);
+ spin_unlock_irqrestore(&node->buf_list_lock, flags);
+
+ /* update buffer internal address */
+ req->frame_params.dma_bufs[buf->node_id].iova = buf->daddr;
+ req->frame_params.dma_bufs[buf->node_id].scp_addr = buf->scp_addr;
+
+ if (!--req->buf_count)
+ mtk_cam_dev_req_try_queue(cam);
+}
+
+static int mtk_cam_vb2_buf_init(struct vb2_buffer *vb)
+{
+ struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vb->vb2_queue);
+ struct mtk_cam_dev *cam = vb2_get_drv_priv(vb->vb2_queue);
+ struct device *dev = cam->dev;
+ struct mtk_cam_dev_buffer *buf;
+ dma_addr_t addr;
+
+ buf = mtk_cam_vb2_buf_to_dev_buf(vb);
+ buf->node_id = node->id;
+ buf->daddr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ buf->scp_addr = 0;
+
+ /* SCP address is only valid for meta input buffer */
+ if (!node->desc.smem_alloc)
+ return 0;
+
+ buf = mtk_cam_vb2_buf_to_dev_buf(vb);
+ /* Use coherent address to get iova address */
+ addr = dma_map_resource(dev, buf->daddr, vb->planes[0].length,
+ DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC);
+ if (dma_mapping_error(dev, addr)) {
+ dev_err(dev, "failed to map meta addr:%pad\n", &buf->daddr);
+ return -EFAULT;
+ }
+ buf->scp_addr = buf->daddr;
+ buf->daddr = addr;
+
+ return 0;
+}
+
+static int mtk_cam_vb2_buf_prepare(struct vb2_buffer *vb)
+{
+ struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vb->vb2_queue);
+ struct mtk_cam_dev *cam = vb2_get_drv_priv(vb->vb2_queue);
+ struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb);
+ const struct v4l2_format *fmt = &node->vdev_fmt;
+ unsigned int size;
+
+ if (vb->vb2_queue->type == V4L2_BUF_TYPE_META_OUTPUT ||
+ vb->vb2_queue->type == V4L2_BUF_TYPE_META_CAPTURE)
+ size = fmt->fmt.meta.buffersize;
+ else
+ size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;
+
+ if (vb2_plane_size(vb, 0) < size) {
+ dev_dbg(cam->dev, "plane size is too small:%lu<%u\n",
+ vb2_plane_size(vb, 0), size);
+ return -EINVAL;
+ }
+
+ if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+ if (vb2_get_plane_payload(vb, 0) != size) {
+ dev_dbg(cam->dev, "plane payload is mismatch:%lu:%u\n",
+ vb2_get_plane_payload(vb, 0), size);
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ v4l2_buf->field = V4L2_FIELD_NONE;
+ vb2_set_plane_payload(vb, 0, size);
+
+ return 0;
+}
+
+static void mtk_cam_vb2_buf_cleanup(struct vb2_buffer *vb)
+{
+ struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vb->vb2_queue);
+ struct mtk_cam_dev *cam = vb2_get_drv_priv(vb->vb2_queue);
+ struct mtk_cam_dev_buffer *buf;
+ struct device *dev = cam->dev;
+
+ if (!node->desc.smem_alloc)
+ return;
+
+ buf = mtk_cam_vb2_buf_to_dev_buf(vb);
+ dma_unmap_page_attrs(dev, buf->daddr,
+ vb->planes[0].length,
+ DMA_BIDIRECTIONAL,
+ DMA_ATTR_SKIP_CPU_SYNC);
+}
+
+static void mtk_cam_vb2_request_complete(struct vb2_buffer *vb)
+{
+ struct mtk_cam_dev *cam = vb2_get_drv_priv(vb->vb2_queue);
+
+ dev_dbg(cam->dev, "%s\n", __func__);
+}
+
+static int mtk_cam_vb2_queue_setup(struct vb2_queue *vq,
+ unsigned int *num_buffers,
+ unsigned int *num_planes,
+ unsigned int sizes[],
+ struct device *alloc_devs[])
+{
+ struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vq);
+ unsigned int max_buffer_count = node->desc.max_buf_count;
+ const struct v4l2_format *fmt = &node->vdev_fmt;
+ unsigned int size;
+
+ /* Check the limitation of buffer size */
+ if (max_buffer_count)
+ *num_buffers = clamp_val(*num_buffers, 1, max_buffer_count);
+
+ if (node->desc.smem_alloc)
+ vq->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
+ else
+ vq->dma_attrs |= DMA_ATTR_NON_CONSISTENT;
+
+ if (vq->type == V4L2_BUF_TYPE_META_OUTPUT ||
+ vq->type == V4L2_BUF_TYPE_META_CAPTURE)
+ size = fmt->fmt.meta.buffersize;
+ else
+ size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;
+
+ /* Add for q.create_bufs with fmt.g_sizeimage(p) / 2 test */
+ if (*num_planes) {
+ if (sizes[0] < size || *num_planes != 1)
+ return -EINVAL;
+ } else {
+ *num_planes = 1;
+ sizes[0] = size;
+ }
+
+ return 0;
+}
+
+static void mtk_cam_vb2_return_all_buffers(struct mtk_cam_dev *cam,
+ struct mtk_cam_video_device *node,
+ enum vb2_buffer_state state)
+{
+ struct mtk_cam_dev_buffer *buf, *buf_prev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&node->buf_list_lock, flags);
+ list_for_each_entry_safe(buf, buf_prev, &node->buf_list, list) {
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vbb.vb2_buf, state);
+ }
+ spin_unlock_irqrestore(&node->buf_list_lock, flags);
+}
+
+static int mtk_cam_vb2_start_streaming(struct vb2_queue *vq,
+ unsigned int count)
+{
+ struct mtk_cam_dev *cam = vb2_get_drv_priv(vq);
+ struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vq);
+ struct device *dev = cam->dev;
+ int ret;
+
+ if (!node->enabled) {
+ dev_err(dev, "Node:%d is not enabled\n", node->id);
+ ret = -ENOLINK;
+ goto fail_ret_buf;
+ }
+
+ mutex_lock(&cam->op_lock);
+ /* Start streaming of the whole pipeline now*/
+ if (!cam->pipeline.streaming_count) {
+ ret = media_pipeline_start(&node->vdev.entity, &cam->pipeline);
+ if (ret) {
+ dev_err(dev, "failed to start pipeline:%d\n", ret);
+ goto fail_unlock;
+ }
+ mtk_cam_dev_init_stream(cam);
+ ret = mtk_isp_hw_init(cam);
+ if (ret) {
+ dev_err(dev, "failed to init HW:%d\n", ret);
+ goto fail_stop_pipeline;
+ }
+ }
+
+ /* Media links are fixed after media_pipeline_start */
+ cam->stream_count++;
+ dev_dbg(dev, "%s: count info:%d:%d\n", __func__, cam->stream_count,
+ cam->enabled_count);
+ if (cam->stream_count < cam->enabled_count) {
+ mutex_unlock(&cam->op_lock);
+ return 0;
+ }
+
+ /* Stream on sub-devices node */
+ ret = v4l2_subdev_call(&cam->subdev, video, s_stream, 1);
+ if (ret)
+ goto fail_no_stream;
+ mutex_unlock(&cam->op_lock);
+
+ return 0;
+
+fail_no_stream:
+ cam->stream_count--;
+fail_stop_pipeline:
+ if (cam->stream_count == 0)
+ media_pipeline_stop(&node->vdev.entity);
+fail_unlock:
+ mutex_unlock(&cam->op_lock);
+fail_ret_buf:
+ mtk_cam_vb2_return_all_buffers(cam, node, VB2_BUF_STATE_QUEUED);
+
+ return ret;
+}
+
+static void mtk_cam_vb2_stop_streaming(struct vb2_queue *vq)
+{
+ struct mtk_cam_dev *cam = vb2_get_drv_priv(vq);
+ struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vq);
+ struct device *dev = cam->dev;
+
+ mutex_lock(&cam->op_lock);
+ dev_dbg(dev, "%s node:%d count info:%d\n", __func__, node->id,
+ cam->stream_count);
+ /* Check the first node to stream-off */
+ if (cam->stream_count == cam->enabled_count)
+ v4l2_subdev_call(&cam->subdev, video, s_stream, 0);
+
+ mtk_cam_vb2_return_all_buffers(cam, node, VB2_BUF_STATE_ERROR);
+ cam->stream_count--;
+ if (cam->stream_count) {
+ mutex_unlock(&cam->op_lock);
+ return;
+ }
+ mutex_unlock(&cam->op_lock);
+
+ mtk_cam_dev_req_cleanup(cam);
+ media_pipeline_stop(&node->vdev.entity);
+}
+
+static int mtk_cam_vidioc_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct mtk_cam_dev *cam = video_drvdata(file);
+
+ strscpy(cap->driver, dev_driver_string(cam->dev), sizeof(cap->driver));
+ strscpy(cap->card, dev_driver_string(cam->dev), sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+ dev_name(cam->dev));
+
+ return 0;
+}
+
+static int mtk_cam_vidioc_enum_fmt(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f)
+{
+ struct mtk_cam_video_device *node = file_to_mtk_cam_node(file);
+
+ if (f->index >= node->desc.num_fmts)
+ return -EINVAL;
+
+ /* f->description is filled in v4l_fill_fmtdesc function */
+ f->pixelformat = node->desc.fmts[f->index].fmt.pix_mp.pixelformat;
+ f->flags = 0;
+
+ return 0;
+}
+
+static int mtk_cam_vidioc_g_fmt(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct mtk_cam_video_device *node = file_to_mtk_cam_node(file);
+
+ f->fmt = node->vdev_fmt.fmt;
+
+ return 0;
+}
+
+static int mtk_cam_vidioc_try_fmt(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct mtk_cam_dev *cam = video_drvdata(file);
+ struct mtk_cam_video_device *node = file_to_mtk_cam_node(file);
+ struct device *dev = cam->dev;
+ const struct v4l2_format *dev_fmt;
+ struct v4l2_format try_fmt;
+
+ memset(&try_fmt, 0, sizeof(try_fmt));
+ try_fmt.type = f->type;
+
+ /* Validate pixelformat */
+ dev_fmt = mtk_cam_dev_find_fmt(&node->desc, f->fmt.pix_mp.pixelformat);
+ if (!dev_fmt) {
+ dev_dbg(dev, "unknown fmt:%d\n", f->fmt.pix_mp.pixelformat);
+ dev_fmt = &node->desc.fmts[node->desc.default_fmt_idx];
+ }
+ try_fmt.fmt.pix_mp.pixelformat = dev_fmt->fmt.pix_mp.pixelformat;
+
+ /* Validate image width & height range */
+ try_fmt.fmt.pix_mp.width = clamp_val(f->fmt.pix_mp.width,
+ IMG_MIN_WIDTH, IMG_MAX_WIDTH);
+ try_fmt.fmt.pix_mp.height = clamp_val(f->fmt.pix_mp.height,
+ IMG_MIN_HEIGHT, IMG_MAX_HEIGHT);
+ /* 4 bytes alignment for width */
+ try_fmt.fmt.pix_mp.width = ALIGN(try_fmt.fmt.pix_mp.width, 4);
+
+ /* Only support one plane */
+ try_fmt.fmt.pix_mp.num_planes = 1;
+
+ /* bytesperline & sizeimage calculation */
+ cal_image_pix_mp(cam, node->id, &try_fmt.fmt.pix_mp);
+
+ /* Constant format fields */
+ try_fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_SRGB;
+ try_fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
+ try_fmt.fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ try_fmt.fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
+ try_fmt.fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_SRGB;
+
+ *f = try_fmt;
+
+ return 0;
+}
+
+static int mtk_cam_vidioc_s_fmt(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct mtk_cam_dev *cam = video_drvdata(file);
+ struct mtk_cam_video_device *node = file_to_mtk_cam_node(file);
+
+ if (vb2_is_busy(node->vdev.queue)) {
+ dev_dbg(cam->dev, "%s: queue is busy\n", __func__);
+ return -EBUSY;
+ }
+
+ /* Get the valid format */
+ mtk_cam_vidioc_try_fmt(file, fh, f);
+ /* Configure to video device */
+ node->vdev_fmt = *f;
+
+ return 0;
+}
+
+static int mtk_cam_vidioc_enum_framesizes(struct file *filp, void *priv,
+ struct v4l2_frmsizeenum *sizes)
+{
+ struct mtk_cam_video_device *node = file_to_mtk_cam_node(filp);
+ const struct v4l2_format *dev_fmt;
+
+ dev_fmt = mtk_cam_dev_find_fmt(&node->desc, sizes->pixel_format);
+ if (!dev_fmt || sizes->index)
+ return -EINVAL;
+
+ sizes->type = node->desc.frmsizes->type;
+ memcpy(&sizes->stepwise, &node->desc.frmsizes->stepwise,
+ sizeof(sizes->stepwise));
+
+ return 0;
+}
+
+static int mtk_cam_vidioc_meta_enum_fmt(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f)
+{
+ struct mtk_cam_video_device *node = file_to_mtk_cam_node(file);
+
+ if (f->index)
+ return -EINVAL;
+
+ /* f->description is filled in v4l_fill_fmtdesc function */
+ f->pixelformat = node->vdev_fmt.fmt.meta.dataformat;
+ f->flags = 0;
+
+ return 0;
+}
+
+static int mtk_cam_vidioc_g_meta_fmt(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct mtk_cam_video_device *node = file_to_mtk_cam_node(file);
+
+ f->fmt.meta.dataformat = node->vdev_fmt.fmt.meta.dataformat;
+ f->fmt.meta.buffersize = node->vdev_fmt.fmt.meta.buffersize;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops mtk_cam_subdev_core_ops = {
+ .subscribe_event = mtk_cam_sd_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops mtk_cam_subdev_video_ops = {
+ .s_stream = mtk_cam_sd_s_stream,
+};
+
+static const struct v4l2_subdev_ops mtk_cam_subdev_ops = {
+ .core = &mtk_cam_subdev_core_ops,
+ .video = &mtk_cam_subdev_video_ops,
+};
+
+static const struct media_entity_operations mtk_cam_media_entity_ops = {
+ .link_setup = mtk_cam_media_link_setup,
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+static const struct vb2_ops mtk_cam_vb2_ops = {
+ .queue_setup = mtk_cam_vb2_queue_setup,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .buf_init = mtk_cam_vb2_buf_init,
+ .buf_prepare = mtk_cam_vb2_buf_prepare,
+ .start_streaming = mtk_cam_vb2_start_streaming,
+ .stop_streaming = mtk_cam_vb2_stop_streaming,
+ .buf_queue = mtk_cam_vb2_buf_queue,
+ .buf_cleanup = mtk_cam_vb2_buf_cleanup,
+ .buf_request_complete = mtk_cam_vb2_request_complete,
+};
+
+static const struct v4l2_file_operations mtk_cam_v4l2_fops = {
+ .unlocked_ioctl = video_ioctl2,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = v4l2_compat_ioctl32,
+#endif
+};
+
+static const struct media_device_ops mtk_cam_media_ops = {
+ .link_notify = v4l2_pipeline_link_notify,
+ .req_alloc = mtk_cam_req_alloc,
+ .req_free = mtk_cam_req_free,
+ .req_validate = vb2_request_validate,
+ .req_queue = mtk_cam_req_queue,
+};
+
+static int mtk_cam_media_register(struct mtk_cam_dev *cam,
+ struct media_device *media_dev)
+{
+ /* Reserved MTK_CAM_CIO_PAD_SINK + 1 pads to use */
+ unsigned int num_pads = MTK_CAM_CIO_PAD_SINK + 1;
+ struct device *dev = cam->dev;
+ int i, ret;
+
+ media_dev->dev = cam->dev;
+ strscpy(media_dev->model, dev_driver_string(dev),
+ sizeof(media_dev->model));
+ snprintf(media_dev->bus_info, sizeof(media_dev->bus_info),
+ "platform:%s", dev_name(dev));
+ media_dev->hw_revision = 0;
+ media_device_init(media_dev);
+ media_dev->ops = &mtk_cam_media_ops;
+
+ ret = media_device_register(media_dev);
+ if (ret) {
+ dev_err(dev, "failed to register media device:%d\n", ret);
+ return ret;
+ }
+
+ /* Initialize subdev pads */
+ cam->subdev_pads = devm_kcalloc(dev, num_pads,
+ sizeof(*cam->subdev_pads),
+ GFP_KERNEL);
+ if (!cam->subdev_pads) {
+ dev_err(dev, "failed to allocate subdev_pads\n");
+ ret = -ENOMEM;
+ goto fail_media_unreg;
+ }
+
+ ret = media_entity_pads_init(&cam->subdev.entity, num_pads,
+ cam->subdev_pads);
+ if (ret) {
+ dev_err(dev, "failed to initialize media pads:%d\n", ret);
+ goto fail_media_unreg;
+ }
+
+ /* Initialize all pads with MEDIA_PAD_FL_SOURCE */
+ for (i = 0; i < num_pads; i++)
+ cam->subdev_pads[i].flags = MEDIA_PAD_FL_SOURCE;
+
+ /* Customize the last one pad as CIO sink pad. */
+ cam->subdev_pads[MTK_CAM_CIO_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+
+ return 0;
+
+fail_media_unreg:
+ media_device_unregister(&cam->media_dev);
+ media_device_cleanup(&cam->media_dev);
+
+ return ret;
+}
+
+static int
+mtk_cam_video_register_device(struct mtk_cam_dev *cam,
+ struct mtk_cam_video_device *node)
+{
+ struct device *dev = cam->dev;
+ struct video_device *vdev = &node->vdev;
+ struct vb2_queue *vbq = &node->vbq;
+ unsigned int output = V4L2_TYPE_IS_OUTPUT(node->desc.buf_type);
+ unsigned int link_flags = node->desc.link_flags;
+ int ret;
+
+ /* Initialize mtk_cam_video_device */
+ if (link_flags & MEDIA_LNK_FL_IMMUTABLE)
+ node->enabled = true;
+ else
+ node->enabled = false;
+ mtk_cam_dev_load_default_fmt(cam, &node->desc, &node->vdev_fmt);
+
+ cam->subdev_pads[node->id].flags = output ?
+ MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
+
+ /* Initialize media entities */
+ ret = media_entity_pads_init(&vdev->entity, 1, &node->vdev_pad);
+ if (ret) {
+ dev_err(dev, "failed to initialize media pad:%d\n", ret);
+ return ret;
+ }
+ node->vdev_pad.flags = output ? MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK;
+
+ /* Initialize vbq */
+ vbq->type = node->desc.buf_type;
+ if (vbq->type == V4L2_BUF_TYPE_META_OUTPUT)
+ vbq->io_modes = VB2_MMAP;
+ else
+ vbq->io_modes = VB2_MMAP | VB2_DMABUF;
+
+ if (node->desc.smem_alloc) {
+ vbq->bidirectional = 1;
+ vbq->dev = cam->smem_dev;
+ } else {
+ vbq->dev = dev;
+ }
+ vbq->ops = &mtk_cam_vb2_ops;
+ vbq->mem_ops = &vb2_dma_contig_memops;
+ vbq->buf_struct_size = sizeof(struct mtk_cam_dev_buffer);
+ vbq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ if (output)
+ vbq->timestamp_flags |= V4L2_BUF_FLAG_TSTAMP_SRC_EOF;
+ else
+ vbq->timestamp_flags |= V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
+ /* No minimum buffers limitation */
+ vbq->min_buffers_needed = 0;
+ vbq->drv_priv = cam;
+ vbq->lock = &node->vdev_lock;
+ vbq->supports_requests = true;
+ vbq->requires_requests = true;
+
+ ret = vb2_queue_init(vbq);
+ if (ret) {
+ dev_err(dev, "failed to init. vb2 queue:%d\n", ret);
+ goto fail_media_clean;
+ }
+
+ /* Initialize vdev */
+ snprintf(vdev->name, sizeof(vdev->name), "%s %s",
+ dev_driver_string(dev), node->desc.name);
+ /* set cap/type/ioctl_ops of the video device */
+ vdev->device_caps = node->desc.cap | V4L2_CAP_STREAMING;
+ vdev->ioctl_ops = node->desc.ioctl_ops;
+ vdev->fops = &mtk_cam_v4l2_fops;
+ vdev->release = video_device_release_empty;
+ vdev->lock = &node->vdev_lock;
+ vdev->v4l2_dev = &cam->v4l2_dev;
+ vdev->queue = &node->vbq;
+ vdev->vfl_dir = output ? VFL_DIR_TX : VFL_DIR_RX;
+ vdev->entity.function = MEDIA_ENT_F_IO_V4L;
+ vdev->entity.ops = NULL;
+ video_set_drvdata(vdev, cam);
+ dev_dbg(dev, "registered vdev:%d:%s\n", node->id, vdev->name);
+
+ /* Initialize miscellaneous variables */
+ mutex_init(&node->vdev_lock);
+ INIT_LIST_HEAD(&node->buf_list);
+ spin_lock_init(&node->buf_list_lock);
+
+ ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+ if (ret) {
+ dev_err(dev, "failed to register vde:%d\n", ret);
+ goto fail_vb2_rel;
+ }
+
+ /* Create link between video node and the subdev pad */
+ if (output) {
+ ret = media_create_pad_link(&vdev->entity, 0,
+ &cam->subdev.entity,
+ node->id, link_flags);
+ } else {
+ ret = media_create_pad_link(&cam->subdev.entity,
+ node->id, &vdev->entity, 0,
+ link_flags);
+ }
+ if (ret)
+ goto fail_vdev_ureg;
+
+ return 0;
+
+fail_vdev_ureg:
+ video_unregister_device(vdev);
+fail_vb2_rel:
+ mutex_destroy(&node->vdev_lock);
+ vb2_queue_release(vbq);
+fail_media_clean:
+ media_entity_cleanup(&vdev->entity);
+
+ return ret;
+}
+
+static void
+mtk_cam_video_unregister_device(struct mtk_cam_video_device *node)
+{
+ video_unregister_device(&node->vdev);
+ media_entity_cleanup(&node->vdev.entity);
+ mutex_destroy(&node->vdev_lock);
+}
+
+static int mtk_cam_v4l2_register(struct mtk_cam_dev *cam)
+{
+ struct device *dev = cam->dev;
+ int i, ret;
+
+ /* Set up media device & pads */
+ ret = mtk_cam_media_register(cam, &cam->media_dev);
+ if (ret)
+ return ret;
+ dev_info(dev, "Registered media%d\n", cam->media_dev.devnode->minor);
+
+ /* Set up v4l2 device */
+ cam->v4l2_dev.mdev = &cam->media_dev;
+ ret = v4l2_device_register(dev, &cam->v4l2_dev);
+ if (ret) {
+ dev_err(dev, "failed to register V4L2 device:%d\n", ret);
+ goto fail_media_unreg;
+ }
+ dev_info(dev, "Registered %s\n", cam->v4l2_dev.name);
+
+ /* Initialize subdev */
+ v4l2_subdev_init(&cam->subdev, &mtk_cam_subdev_ops);
+ cam->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
+ cam->subdev.entity.ops = &mtk_cam_media_entity_ops;
+ cam->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE |
+ V4L2_SUBDEV_FL_HAS_EVENTS;
+ snprintf(cam->subdev.name, sizeof(cam->subdev.name),
+ "%s", dev_driver_string(dev));
+ v4l2_set_subdevdata(&cam->subdev, cam);
+
+ ret = v4l2_device_register_subdev(&cam->v4l2_dev, &cam->subdev);
+ if (ret) {
+ dev_err(dev, "failed to initialize subdev:%d\n", ret);
+ goto fail_clean_media_entiy;
+ }
+ dev_dbg(dev, "registered %s\n", cam->subdev.name);
+
+ /* Create video nodes and links */
+ for (i = 0; i < MTK_CAM_P1_TOTAL_NODES; i++) {
+ struct mtk_cam_video_device *node = &cam->vdev_nodes[i];
+
+ node->id = node->desc.id;
+ ret = mtk_cam_video_register_device(cam, node);
+ if (ret)
+ goto fail_vdev_unreg;
+ }
+ vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
+ return 0;
+
+fail_vdev_unreg:
+ for (i--; i >= 0; i--)
+ mtk_cam_video_unregister_device(&cam->vdev_nodes[i]);
+fail_clean_media_entiy:
+ media_entity_cleanup(&cam->subdev.entity);
+ v4l2_device_unregister(&cam->v4l2_dev);
+fail_media_unreg:
+ media_device_unregister(&cam->media_dev);
+ media_device_cleanup(&cam->media_dev);
+
+ return ret;
+}
+
+static int mtk_cam_v4l2_unregister(struct mtk_cam_dev *cam)
+{
+ int i;
+
+ for (i = 0; i < MTK_CAM_P1_TOTAL_NODES; i++)
+ mtk_cam_video_unregister_device(&cam->vdev_nodes[i]);
+
+ vb2_dma_contig_clear_max_seg_size(cam->dev);
+ v4l2_device_unregister_subdev(&cam->subdev);
+ v4l2_device_unregister(&cam->v4l2_dev);
+ media_entity_cleanup(&cam->subdev.entity);
+ media_device_unregister(&cam->media_dev);
+ media_device_cleanup(&cam->media_dev);
+
+ return 0;
+}
+
+static int mtk_cam_dev_notifier_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+ struct mtk_cam_dev *cam =
+ container_of(notifier, struct mtk_cam_dev, notifier);
+
+ if (!(sd->entity.function & MEDIA_ENT_F_VID_IF_BRIDGE)) {
+ dev_dbg(cam->dev, "no MEDIA_ENT_F_VID_IF_BRIDGE function\n");
+ return -ENODEV;
+ }
+
+ cam->seninf = sd;
+ dev_dbg(cam->dev, "%s is bound\n", sd->entity.name);
+
+ return 0;
+}
+
+static void mtk_cam_dev_notifier_unbind(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+ struct mtk_cam_dev *cam =
+ container_of(notifier, struct mtk_cam_dev, notifier);
+
+ cam->seninf = NULL;
+ dev_dbg(cam->dev, "%s is unbound\n", sd->entity.name);
+}
+
+static int mtk_cam_dev_notifier_complete(struct v4l2_async_notifier *notifier)
+{
+ struct mtk_cam_dev *cam =
+ container_of(notifier, struct mtk_cam_dev, notifier);
+ struct device *dev = cam->dev;
+ int ret;
+
+ ret = media_create_pad_link(&cam->seninf->entity, MTK_CAM_CIO_PAD_SRC,
+ &cam->subdev.entity, MTK_CAM_CIO_PAD_SINK,
+ MEDIA_LNK_FL_IMMUTABLE |
+ MEDIA_LNK_FL_ENABLED);
+ if (ret) {
+ dev_err(dev, "failed to create pad link %s %s err:%d\n",
+ cam->seninf->entity.name, cam->subdev.entity.name,
+ ret);
+ return ret;
+ }
+
+ ret = v4l2_device_register_subdev_nodes(&cam->v4l2_dev);
+ if (ret) {
+ dev_err(dev, "failed to initialize subdev nodes:%d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+static const struct v4l2_async_notifier_operations mtk_cam_v4l2_async_ops = {
+ .bound = mtk_cam_dev_notifier_bound,
+ .unbind = mtk_cam_dev_notifier_unbind,
+ .complete = mtk_cam_dev_notifier_complete,
+};
+
+static int mtk_cam_v4l2_async_register(struct mtk_cam_dev *cam)
+{
+ struct device *dev = cam->dev;
+ int ret;
+
+ v4l2_async_notifier_init(&cam->notifier);
+ ret = v4l2_async_notifier_parse_fwnode_endpoints(dev,
+ &cam->notifier, sizeof(struct v4l2_async_subdev), NULL);
+ if (ret) {
+ dev_err(dev, "failed to parse fwnode endpoints:%d\n", ret);
+ return ret;
+ }
+
+ cam->notifier.ops = &mtk_cam_v4l2_async_ops;
+ dev_dbg(dev, "mtk_cam v4l2_async_notifier_register\n");
+ ret = v4l2_async_notifier_register(&cam->v4l2_dev, &cam->notifier);
+ if (ret) {
+ dev_err(dev, "failed to register async notifier : %d\n", ret);
+ v4l2_async_notifier_cleanup(&cam->notifier);
+ }
+
+ return ret;
+}
+
+static void mtk_cam_v4l2_async_unregister(struct mtk_cam_dev *cam)
+{
+ v4l2_async_notifier_unregister(&cam->notifier);
+ v4l2_async_notifier_cleanup(&cam->notifier);
+}
+
+static const struct v4l2_ioctl_ops mtk_cam_v4l2_vcap_ioctl_ops = {
+ .vidioc_querycap = mtk_cam_vidioc_querycap,
+ .vidioc_enum_framesizes = mtk_cam_vidioc_enum_framesizes,
+ .vidioc_enum_fmt_vid_cap = mtk_cam_vidioc_enum_fmt,
+ .vidioc_g_fmt_vid_cap_mplane = mtk_cam_vidioc_g_fmt,
+ .vidioc_s_fmt_vid_cap_mplane = mtk_cam_vidioc_s_fmt,
+ .vidioc_try_fmt_vid_cap_mplane = mtk_cam_vidioc_try_fmt,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ioctl_ops mtk_cam_v4l2_meta_cap_ioctl_ops = {
+ .vidioc_querycap = mtk_cam_vidioc_querycap,
+ .vidioc_enum_fmt_meta_cap = mtk_cam_vidioc_meta_enum_fmt,
+ .vidioc_g_fmt_meta_cap = mtk_cam_vidioc_g_meta_fmt,
+ .vidioc_s_fmt_meta_cap = mtk_cam_vidioc_g_meta_fmt,
+ .vidioc_try_fmt_meta_cap = mtk_cam_vidioc_g_meta_fmt,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
+};
+
+static const struct v4l2_ioctl_ops mtk_cam_v4l2_meta_out_ioctl_ops = {
+ .vidioc_querycap = mtk_cam_vidioc_querycap,
+ .vidioc_enum_fmt_meta_out = mtk_cam_vidioc_meta_enum_fmt,
+ .vidioc_g_fmt_meta_out = mtk_cam_vidioc_g_meta_fmt,
+ .vidioc_s_fmt_meta_out = mtk_cam_vidioc_g_meta_fmt,
+ .vidioc_try_fmt_meta_out = mtk_cam_vidioc_g_meta_fmt,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
+};
+
+static const struct v4l2_format meta_fmts[] = {
+ {
+ .fmt.meta = {
+ .dataformat = V4L2_META_FMT_MTISP_PARAMS,
+ .buffersize = 512 * SZ_1K,
+ },
+ },
+ {
+ .fmt.meta = {
+ .dataformat = V4L2_META_FMT_MTISP_3A,
+ .buffersize = 1200 * SZ_1K,
+ },
+ },
+ {
+ .fmt.meta = {
+ .dataformat = V4L2_META_FMT_MTISP_AF,
+ .buffersize = 640 * SZ_1K,
+ },
+ },
+ {
+ .fmt.meta = {
+ .dataformat = V4L2_META_FMT_MTISP_LCS,
+ .buffersize = 288 * SZ_1K,
+ },
+ },
+ {
+ .fmt.meta = {
+ .dataformat = V4L2_META_FMT_MTISP_LMV,
+ .buffersize = 256,
+ },
+ },
+};
+
+static const struct v4l2_format stream_out_fmts[] = {
+ /* This is a default image format */
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR10,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR8,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR12,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR14,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG8,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG10,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG12,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG14,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG8,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG10,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG12,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG14,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB8,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB10,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB12,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB14,
+ },
+ },
+};
+
+static const struct v4l2_format bin_out_fmts[] = {
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR8F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR10F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR12F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR14F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG8F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG10F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG12F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG14F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG8F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG10F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG12F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG14F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB8F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB10F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB12F,
+ },
+ },
+ {
+ .fmt.pix_mp = {
+ .width = IMG_MAX_WIDTH,
+ .height = IMG_MAX_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB14F,
+ },
+ },
+};
+
+static const struct
+mtk_cam_dev_node_desc output_queues[] = {
+ {
+ .id = MTK_CAM_P1_META_IN_0,
+ .name = "meta input",
+ .cap = V4L2_CAP_META_OUTPUT,
+ .buf_type = V4L2_BUF_TYPE_META_OUTPUT,
+ .link_flags = 0,
+ .image = false,
+ .smem_alloc = true,
+ .fmts = meta_fmts,
+ .default_fmt_idx = 0,
+ .max_buf_count = 10,
+ .ioctl_ops = &mtk_cam_v4l2_meta_out_ioctl_ops,
+ },
+};
+
+static const struct
+mtk_cam_dev_node_desc capture_queues[] = {
+ {
+ .id = MTK_CAM_P1_MAIN_STREAM_OUT,
+ .name = "main stream",
+ .cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE,
+ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ .link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED,
+ .image = true,
+ .smem_alloc = false,
+ .dma_port = R_IMGO,
+ .fmts = stream_out_fmts,
+ .num_fmts = ARRAY_SIZE(stream_out_fmts),
+ .default_fmt_idx = 0,
+ .ioctl_ops = &mtk_cam_v4l2_vcap_ioctl_ops,
+ .frmsizes = &(struct v4l2_frmsizeenum) {
+ .index = 0,
+ .type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+ .stepwise = {
+ .max_width = IMG_MAX_WIDTH,
+ .min_width = IMG_MIN_WIDTH,
+ .max_height = IMG_MAX_HEIGHT,
+ .min_height = IMG_MIN_HEIGHT,
+ .step_height = 1,
+ .step_width = 1,
+ },
+ },
+ },
+ {
+ .id = MTK_CAM_P1_PACKED_BIN_OUT,
+ .name = "packed out",
+ .cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE,
+ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ .link_flags = 0,
+ .image = true,
+ .smem_alloc = false,
+ .dma_port = R_RRZO,
+ .fmts = bin_out_fmts,
+ .num_fmts = ARRAY_SIZE(bin_out_fmts),
+ .default_fmt_idx = 0,
+ .ioctl_ops = &mtk_cam_v4l2_vcap_ioctl_ops,
+ .frmsizes = &(struct v4l2_frmsizeenum) {
+ .index = 0,
+ .type = V4L2_FRMSIZE_TYPE_CONTINUOUS,
+ .stepwise = {
+ .max_width = IMG_MAX_WIDTH,
+ .min_width = IMG_MIN_WIDTH,
+ .max_height = IMG_MAX_HEIGHT,
+ .min_height = IMG_MIN_HEIGHT,
+ .step_height = 1,
+ .step_width = 1,
+ },
+ },
+ },
+ {
+ .id = MTK_CAM_P1_META_OUT_0,
+ .name = "partial meta 0",
+ .cap = V4L2_CAP_META_CAPTURE,
+ .buf_type = V4L2_BUF_TYPE_META_CAPTURE,
+ .link_flags = 0,
+ .image = false,
+ .smem_alloc = false,
+ .dma_port = R_AAO | R_FLKO | R_PSO,
+ .fmts = meta_fmts,
+ .default_fmt_idx = 1,
+ .max_buf_count = 5,
+ .ioctl_ops = &mtk_cam_v4l2_meta_cap_ioctl_ops,
+ },
+ {
+ .id = MTK_CAM_P1_META_OUT_1,
+ .name = "partial meta 1",
+ .cap = V4L2_CAP_META_CAPTURE,
+ .buf_type = V4L2_BUF_TYPE_META_CAPTURE,
+ .link_flags = 0,
+ .image = false,
+ .smem_alloc = false,
+ .dma_port = R_AFO,
+ .fmts = meta_fmts,
+ .default_fmt_idx = 2,
+ .max_buf_count = 5,
+ .ioctl_ops = &mtk_cam_v4l2_meta_cap_ioctl_ops,
+ },
+ {
+ .id = MTK_CAM_P1_META_OUT_2,
+ .name = "partial meta 2",
+ .cap = V4L2_CAP_META_CAPTURE,
+ .buf_type = V4L2_BUF_TYPE_META_CAPTURE,
+ .link_flags = 0,
+ .image = false,
+ .smem_alloc = false,
+ .dma_port = R_LCSO,
+ .fmts = meta_fmts,
+ .default_fmt_idx = 3,
+ .max_buf_count = 10,
+ .ioctl_ops = &mtk_cam_v4l2_meta_cap_ioctl_ops,
+ },
+ {
+ .id = MTK_CAM_P1_META_OUT_3,
+ .name = "partial meta 3",
+ .cap = V4L2_CAP_META_CAPTURE,
+ .buf_type = V4L2_BUF_TYPE_META_CAPTURE,
+ .link_flags = 0,
+ .image = false,
+ .smem_alloc = false,
+ .dma_port = R_LMVO,
+ .fmts = meta_fmts,
+ .default_fmt_idx = 4,
+ .max_buf_count = 10,
+ .ioctl_ops = &mtk_cam_v4l2_meta_cap_ioctl_ops,
+ },
+};
+
+/* The helper to configure the device context */
+static void mtk_cam_dev_queue_setup(struct mtk_cam_dev *cam)
+{
+ unsigned int node_idx;
+ int i;
+
+ node_idx = 0;
+ /* Setup the output queue */
+ for (i = 0; i < ARRAY_SIZE(output_queues); i++)
+ cam->vdev_nodes[node_idx++].desc = output_queues[i];
+
+ /* Setup the capture queue */
+ for (i = 0; i < ARRAY_SIZE(capture_queues); i++)
+ cam->vdev_nodes[node_idx++].desc = capture_queues[i];
+}
+
+int mtk_cam_dev_init(struct platform_device *pdev,
+ struct mtk_cam_dev *cam)
+{
+ int ret;
+
+ cam->dev = &pdev->dev;
+ mtk_cam_dev_queue_setup(cam);
+
+ spin_lock_init(&cam->pending_job_lock);
+ spin_lock_init(&cam->running_job_lock);
+ INIT_LIST_HEAD(&cam->pending_job_list);
+ INIT_LIST_HEAD(&cam->running_job_list);
+ mutex_init(&cam->op_lock);
+
+ /* v4l2 sub-device registration */
+ ret = mtk_cam_v4l2_register(cam);
+ if (ret)
+ return ret;
+
+ ret = mtk_cam_v4l2_async_register(cam);
+ if (ret)
+ goto fail_v4l2_unreg;
+
+ return 0;
+
+fail_v4l2_unreg:
+ mutex_destroy(&cam->op_lock);
+ mtk_cam_v4l2_unregister(cam);
+
+ return ret;
+}
+
+void mtk_cam_dev_cleanup(struct mtk_cam_dev *cam)
+{
+ mtk_cam_v4l2_async_unregister(cam);
+ mtk_cam_v4l2_unregister(cam);
+ mutex_destroy(&cam->op_lock);
+}
+
diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.h b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.h
new file mode 100644
index 000000000000..e17e7f37afad
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.h
@@ -0,0 +1,242 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MTK_CAM_H__
+#define __MTK_CAM_H__
+
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
+
+#include "mtk_cam-ipi.h"
+
+#define IMG_MAX_WIDTH 5376
+#define IMG_MAX_HEIGHT 4032
+#define IMG_MIN_WIDTH 80
+#define IMG_MIN_HEIGHT 60
+
+/*
+ * ID enum value for struct mtk_cam_dev_node_desc:id
+ * or mtk_cam_video_device:id
+ */
+enum {
+ MTK_CAM_P1_META_IN_0 = 0,
+ MTK_CAM_P1_MAIN_STREAM_OUT,
+ MTK_CAM_P1_PACKED_BIN_OUT,
+ MTK_CAM_P1_META_OUT_0,
+ MTK_CAM_P1_META_OUT_1,
+ MTK_CAM_P1_META_OUT_2,
+ MTK_CAM_P1_META_OUT_3,
+ MTK_CAM_P1_TOTAL_NODES
+};
+
+/* Supported image format list */
+#define MTK_CAM_IMG_FMT_UNKNOWN 0x0000
+#define MTK_CAM_IMG_FMT_BAYER8 0x2200
+#define MTK_CAM_IMG_FMT_BAYER10 0x2201
+#define MTK_CAM_IMG_FMT_BAYER12 0x2202
+#define MTK_CAM_IMG_FMT_BAYER14 0x2203
+#define MTK_CAM_IMG_FMT_FG_BAYER8 0x2204
+#define MTK_CAM_IMG_FMT_FG_BAYER10 0x2205
+#define MTK_CAM_IMG_FMT_FG_BAYER12 0x2206
+#define MTK_CAM_IMG_FMT_FG_BAYER14 0x2207
+
+/* Supported bayer pixel order */
+#define MTK_CAM_RAW_PXL_ID_B 0
+#define MTK_CAM_RAW_PXL_ID_GB 1
+#define MTK_CAM_RAW_PXL_ID_GR 2
+#define MTK_CAM_RAW_PXL_ID_R 3
+#define MTK_CAM_RAW_PXL_ID_UNKNOWN 4
+
+/*
+ * struct mtk_p1_frame_param - MTK ISP P1 driver frame parameters.
+ *
+ * @frame_seq_no: The frame sequence of frame in driver layer.
+ * @dma_bufs: The DMA buffer address information of enabled DMA nodes.
+ *
+ */
+struct mtk_p1_frame_param {
+ unsigned int frame_seq_no;
+ struct dma_buffer dma_bufs[MTK_CAM_P1_TOTAL_NODES];
+} __packed;
+
+/*
+ * struct mtk_cam_dev_request - MTK camera device request.
+ *
+ * @req: Embedded struct media request.
+ * @frame_params: The frame info. & address info. of enabled DMA nodes.
+ * @frame_work: work queue entry for frame transmission to SCP.
+ * @list: List entry of the object for @struct mtk_cam_dev:
+ * pending_job_list or running_job_list.
+ * @buf_count: Buffer count in this media request.
+ *
+ */
+struct mtk_cam_dev_request {
+ struct media_request req;
+ struct mtk_p1_frame_param frame_params;
+ struct work_struct frame_work;
+ struct list_head list;
+ unsigned int buf_count;
+};
+
+/*
+ * struct mtk_cam_dev_buffer - MTK camera device buffer.
+ *
+ * @vbb: Embedded struct vb2_v4l2_buffer.
+ * @list: List entry of the object for @struct mtk_cam_video_device:
+ * buf_list.
+ * @daddr: The DMA address of this buffer.
+ * @scp_addr: The SCP address of this buffer which
+ * is only supported for meta input node.
+ * @node_id: The vidoe node id which this buffer belongs to.
+ *
+ */
+struct mtk_cam_dev_buffer {
+ struct vb2_v4l2_buffer vbb;
+ struct list_head list;
+ /* Intenal part */
+ dma_addr_t daddr;
+ dma_addr_t scp_addr;
+ unsigned int node_id;
+};
+
+/*
+ * struct mtk_cam_dev_node_desc - MTK camera device node descriptor
+ *
+ * @id: id of the node
+ * @name: name of the node
+ * @cap: supported V4L2 capabilities
+ * @buf_type: supported V4L2 buffer type
+ * @dma_port: the dma ports associated to the node
+ * @link_flags: default media link flags
+ * @smem_alloc: using the smem_dev as alloc device or not
+ * @image: true for image node, false for meta node
+ * @num_fmts: the number of supported node formats
+ * @default_fmt_idx: default format of this node
+ * @max_buf_count: maximum VB2 buffer count
+ * @ioctl_ops: mapped to v4l2_ioctl_ops
+ * @fmts: supported format
+ * @frmsizes: supported V4L2 frame size number
+ *
+ */
+struct mtk_cam_dev_node_desc {
+ u8 id;
+ const char *name;
+ u32 cap;
+ u32 buf_type;
+ u32 dma_port;
+ u32 link_flags;
+ u8 smem_alloc:1;
+ u8 image:1;
+ u8 num_fmts;
+ u8 default_fmt_idx;
+ u8 max_buf_count;
+ const struct v4l2_ioctl_ops *ioctl_ops;
+ const struct v4l2_format *fmts;
+ const struct v4l2_frmsizeenum *frmsizes;
+};
+
+/*
+ * struct mtk_cam_video_device - Mediatek video device structure
+ *
+ * @id: Id for index of mtk_cam_dev:vdev_nodes array
+ * @enabled: Indicate the video device is enabled or not
+ * @desc: The node description of video device
+ * @vdev_fmt: The V4L2 format of video device
+ * @vdev_pad: The media pad graph object of video device
+ * @vbq: A videobuf queue of video device
+ * @vdev: The video device instance
+ * @vdev_lock: Serializes vb2 queue and video device operations
+ * @buf_list: List for enqueue buffers
+ * @buf_list_lock: Lock used to protect buffer list.
+ *
+ */
+struct mtk_cam_video_device {
+ unsigned int id;
+ unsigned int enabled;
+ struct mtk_cam_dev_node_desc desc;
+ struct v4l2_format vdev_fmt;
+ struct media_pad vdev_pad;
+ struct vb2_queue vbq;
+ struct video_device vdev;
+ /* Serializes vb2 queue and video device operations */
+ struct mutex vdev_lock;
+ struct list_head buf_list;
+ /* Lock used to protect buffer list */
+ spinlock_t buf_list_lock;
+};
+
+/*
+ * struct mtk_cam_dev - Mediatek camera device structure.
+ *
+ * @dev: Pointer to device.
+ * @smem_pdev: Pointer to shared memory device.
+ * @pipeline: Media pipeline information.
+ * @media_dev: Media device instance.
+ * @subdev: The V4L2 sub-device instance.
+ * @v4l2_dev: The V4L2 device driver instance.
+ * @notifier: The v4l2_device notifier data.
+ * @subdev_pads: Pointer to the number of media pads of this sub-device.
+ * @vdev_nodes: The array list of mtk_cam_video_device nodes.
+ * @seninf: Pointer to the seninf sub-device.
+ * @sensor: Pointer to the active sensor V4L2 sub-device when streaming on.
+ * @streaming: Indicate the overall streaming status is on or off.
+ * @enabled_dmas: The enabled dma port information when streaming on.
+ * @enabled_count: Number of enabled video nodes
+ * @stream_count: Number of streaming video nodes
+ * @running_job_count: Nunber of running jobs in the HW driver.
+ * @pending_job_list: List to keep the media requests before en-queue into
+ * HW driver.
+ * @pending_job_lock: Protect the pending_job_list data & running_job_count.
+ * @running_job_list: List to keep the media requests after en-queue into
+ * HW driver.
+ * @running_job_lock: Protect the running_job_list data.
+ * @op_lock: Serializes driver's VB2 callback operations.
+ *
+ */
+struct mtk_cam_dev {
+ struct device *dev;
+ struct device *smem_dev;
+ struct media_pipeline pipeline;
+ struct media_device media_dev;
+ struct v4l2_subdev subdev;
+ struct v4l2_device v4l2_dev;
+ struct v4l2_async_notifier notifier;
+ struct media_pad *subdev_pads;
+ struct mtk_cam_video_device vdev_nodes[MTK_CAM_P1_TOTAL_NODES];
+ struct v4l2_subdev *seninf;
+ struct v4l2_subdev *sensor;
+ unsigned int streaming;
+ unsigned int enabled_dmas;
+ unsigned int enabled_count;
+ unsigned int stream_count;
+ unsigned int running_job_count;
+ struct list_head pending_job_list;
+ /* Protect the pending_job_list data */
+ spinlock_t pending_job_lock;
+ struct list_head running_job_list;
+ /* Protect the running_job_list data & running_job_count */
+ spinlock_t running_job_lock;
+ /* Serializes driver's VB2 callback operations */
+ struct mutex op_lock;
+};
+
+int mtk_cam_dev_init(struct platform_device *pdev,
+ struct mtk_cam_dev *cam_dev);
+void mtk_cam_dev_cleanup(struct mtk_cam_dev *cam_dev);
+void mtk_cam_dev_req_try_queue(struct mtk_cam_dev *cam_dev);
+void mtk_cam_dev_dequeue_req_frame(struct mtk_cam_dev *cam_dev,
+ unsigned int frame_seq_no, u64 tstamp);
+void mtk_cam_dev_event_frame_sync(struct mtk_cam_dev *cam_dev,
+ unsigned int frame_seq_no);
+
+#endif /* __MTK_CAM_H__ */
--
2.18.0
^ permalink raw reply related
* [RFC, v4, 3/4] media: platform: Add Mediatek ISP P1 image & meta formats
From: Jungo Lin @ 2019-08-07 12:48 UTC (permalink / raw)
To: tfiga, hverkuil-cisco, laurent.pinchart, matthias.bgg, mchehab
Cc: shik, devicetree, Sean.Cheng, suleiman, Rynn.Wu, srv_heupstream,
robh, ryan.yu, Jerry-ch.Chen, frankie.chiu, jungo.lin, sj.huang,
yuzhao, linux-mediatek, zwisler, ddavenport, frederic.chen,
linux-arm-kernel, linux-media
In-Reply-To: <20190807124803.29884-1-jungo.lin@mediatek.com>
Add packed/full-g bayer formats with 8/10/12/14 bit
for image output. Add Pass 1 (P1) specific meta formats for
parameter processing and 3A/other statistics.
(The current metadata format used in meta input and partial
meta nodes is only a temporary solution to kick off the driver
development and is not ready to be reviewed yet.)
Signed-off-by: Jungo Lin <jungo.lin@mediatek.com>
---
.../media/uapi/v4l/pixfmt-mtisp-sbggr10.rst | 65 +++++++++++
.../media/uapi/v4l/pixfmt-mtisp-sbggr10f.rst | 90 ++++++++++++++
.../media/uapi/v4l/pixfmt-mtisp-sbggr12.rst | 61 ++++++++++
.../media/uapi/v4l/pixfmt-mtisp-sbggr12f.rst | 110 ++++++++++++++++++
.../media/uapi/v4l/pixfmt-mtisp-sbggr14.rst | 73 ++++++++++++
.../media/uapi/v4l/pixfmt-mtisp-sbggr14f.rst | 110 ++++++++++++++++++
.../media/uapi/v4l/pixfmt-mtisp-sbggr8.rst | 51 ++++++++
.../media/uapi/v4l/pixfmt-mtisp-sbggr8f.rst | 78 +++++++++++++
Documentation/media/uapi/v4l/pixfmt-rgb.rst | 8 ++
drivers/media/v4l2-core/v4l2-ioctl.c | 37 ++++++
include/uapi/linux/videodev2.h | 39 +++++++
11 files changed, 722 insertions(+)
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr10.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr10f.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr12.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr12f.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr14.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr14f.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr8.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr8f.rst
diff --git a/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr10.rst b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr10.rst
new file mode 100644
index 000000000000..534edb4f0fd4
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr10.rst
@@ -0,0 +1,65 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-pix-fmt-mtisp-sbggr10:
+.. _v4l2-pix-fmt-mtisp-sgbrg10:
+.. _v4l2-pix-fmt-mtisp-sgrbg10:
+.. _v4l2-pix-fmt-mtisp-srggb10:
+
+*******************************
+V4L2_PIX_FMT_MTISP_SBGGR10 ('MBBA'), V4L2_PIX_FMT_MTISP_SGBRG10('MBGA'), V4L2_PIX_FMT_MTISP_SGRBG10('MBgA'), V4L2_PIX_FMT_MTISP_SRGGB10('MBRA')
+*******************************
+
+10-bit Packed Bayer formats.
+
+Description
+===========
+
+These four pixel formats are used by Mediatek ISP P1.
+This is a packed format, meaning all the data bits for a pixel lying
+next to each other with no padding in memory, with a depth of 10 bits per pixel.
+The least significant byte is stored at lower memory addresses (little-endian).
+The RGB byte order follows raw sRGB / Bayer format from sensor.
+They are conventionally described as GRGR... BGBG..., RGRG... GBGB..., etc.
+Below is an example of conventional RGB byte order BGGR.
+
+**Byte Order.**
+Each cell is one byte.
+
+pixels cross the byte boundary and have a ratio of 5 bytes for each 4 pixels.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - start + 0:
+ - B\ :sub:`00low bits 7--0`
+ - G\ :sub:`01low bits 5--0` (bits 7--2) B\ :sub:`00high bits 9--8`\ (bits 1--0)
+ * - start + 2:
+ - B\ :sub:`02low bits 3--0`\ (bits 7--4) G\ :sub:`01high bits 9--6`\ (bits 3--0)
+ - G\ :sub:`03low bits 1--0`\ (bits 7--6) B\ :sub:`02high bits 9--4`\ (bits 5--0)
+ * - start + 4:
+ - G\ :sub:`03high bits 9--2`
+ * - start + 6:
+ - G\ :sub:`10low bits 7--0`
+ - R\ :sub:`11low bits 5--0`\ (bits 7--2) G\ :sub:`10high bits 9--8`\ (bits 1--0)
+ * - start + 8:
+ - G\ :sub:`12low bits 3--0`\ (bits 7--4) R\ :sub:`11high bits 9--6`\ (bits 3--0)
+ - R\ :sub:`13low bits 1--0`\ (bits 7--6) G\ :sub:`12high bits 9--4`\ (bits 5--0)
+ * - start + 10:
+ - R\ :sub:`13high bits 9--2`
+ * - start + 12:
+ - B\ :sub:`20low bits 7--0`
+ - G\ :sub:`21low bits 5--0`\ (bits 7--2) B\ :sub:`20high bits 9--8`\ (bits 1--0)
+ * - start + 14:
+ - B\ :sub:`22low bits 3--0`\ (bits 7--4) G\ :sub:`21high bits 9--6`\ (bits 3--0)
+ - G\ :sub:`23low bits 1--0`\ (bits 7--6) B\ :sub:`22high bits 9--4`\ (bits 5--0)
+ * - start + 16:
+ - G\ :sub:`23high bits 9--2`
+ * - start + 18:
+ - G\ :sub:`30low bits 7--0`
+ - R\ :sub:`31low bits 5--0`\ (bits 7--2) G\ :sub:`30high bits 9--8`\ (bits 1--0)
+ * - start + 20:
+ - G\ :sub:`32low bits 3--0`\ (bits 7--4) R\ :sub:`31high bits 9--6`\ (bits 3--0)
+ - R\ :sub:`33low bits 1--0`\ (bits 7--6) G\ :sub:`32high bits 9--4`\ (bits 5--0)
+ * - start + 22:
+ - R\ :sub:`33high bits 9--2` (bits 7--0)
\ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr10f.rst b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr10f.rst
new file mode 100644
index 000000000000..7be527711602
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr10f.rst
@@ -0,0 +1,90 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-pix-fmt-mtisp-sbggr10f:
+.. _v4l2-pix-fmt-mtisp-sgbrg10f:
+.. _v4l2-pix-fmt-mtisp-sgrbg10f:
+.. _v4l2-pix-fmt-mtisp-srggb10f:
+
+*******************************
+V4L2_PIX_FMT_MTISP_SBGGR10F ('MFBA'), V4L2_PIX_FMT_MTISP_SGBRG10F('MFGA'), V4L2_PIX_FMT_MTISP_SGRBG10F('MFgA'), V4L2_PIX_FMT_MTISP_SRGGB10F('MFRA')
+*******************************
+
+10-bit Packed Full-G Bayer formats.
+
+Description
+===========
+
+These four pixel formats are used by Mediatek ISP P1.
+This is a packed format with a depth of 10 bits per sample with every 4 pixels.
+Full-G means 1 more pixel for green channel every 2 pixels.
+The least significant byte is stored at lower memory addresses (little-endian).
+The RGB byte order follows raw sRGB / Bayer format from sensor. They are conventionally
+described as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example of conventional
+RGB byte order BGGR.
+
+**Bit-packed representation.**
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - B\ :sub:`00`
+ - FG\ :sub:`01`
+ - G\ :sub:`02`
+ - B\ :sub:`03`
+ - FG\ :sub:`04`
+ - G\ :sub:`05`
+ * - G\ :sub:`10`
+ - R\ :sub:`11`
+ - FG\ :sub:`12`
+ - G\ :sub:`13`
+ - R\ :sub:`14`
+ - FG\ :sub:`15`
+
+**Byte Order.**
+Each cell is one byte.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - start + 0:
+ - B\ :sub:`00low bits 7--0`
+ - FG\ :sub:`01low bits 5--0`\ (bits 7--2) B\ :sub:`00high bits 9--8`\ (bits 1--0)
+ - G\ :sub:`02low bits 3--0`\ (bits 7--4) FG\ :sub:`01high bits 9--6`\ (bits 3--0)
+ - B\ :sub:`03low bits 1--0`\ (bits 7--6) G\ :sub:`02high bits 9--4`\ (bits 5--0)
+ * - start + 4:
+ - B\ :sub:`03high bits 9--2`
+ - FG\ :sub:`04low bits 7--0`
+ - G\ :sub:`05low bits 5--0`\ (bits 7--2) FG\ :sub:`04high bits 9--8`\ (bits 1--0)
+ - G\ :sub:`05high bits 3--0`
+ * - start + 8:
+ - G\ :sub:`10low bits 7--0`
+ - R\ :sub:`11low bits 5--0`\ (bits 7--2) G\ :sub:`10high bits 9--8`\ (bits 1--0)
+ - FG\ :sub:`12low bits 3--0`\ (bits 7--4) R\ :sub:`11high bits 9--6`\ (bits 3--0)
+ - G\ :sub:`13low bits 1--0`\ (bits 7--6) FG\ :sub:`12high bits 9--4`\ (bits 5--0)
+ * - start + 12:
+ - G\ :sub:`13high bits 9--2`
+ - R\ :sub:`14low bits 7--0`
+ - FG\ :sub:`15low bits 5--0`\ (bits 7--2) R\ :sub:`14high bits 9--8`\ (bits 1--0)
+ - FG\ :sub:`15high bits 3--0`
+ * - start + 16:
+ - B\ :sub:`20low bits 7--0`
+ - FG\ :sub:`21low bits 5--0`\ (bits 7--2) B\ :sub:`20high bits 9--8`\ (bits 1--0)
+ - G\ :sub:`22low bits 3--0`\ (bits 7--4) FG\ :sub:`21high bits 9--6`\ (bits 3--0)
+ - B\ :sub:`23low bits 1--0`\ (bits 7--6) G\ :sub:`22high bits 9--4`\ (bits 5--0)
+ * - start + 20:
+ - B\ :sub:`23high bits 9--2`
+ - FG\ :sub:`24low bits 7--0`
+ - G\ :sub:`25low bits 5--0`\ (bits 7--2) FG\ :sub:`24high bits 9--8`\ (bits 1--0)
+ - G\ :sub:`25high bits 3--0`
+ * - start + 24:
+ - G\ :sub:`30low bits 7--0`
+ - R\ :sub:`31low bits 5--0`\ (bits 7--2) G\ :sub:`30high bits 9--8`\ (bits 1--0)
+ - FG\ :sub:`32low bits 3--0`\ (bits 7--4) R\ :sub:`31high bits 9--6`\ (bits 3--0)
+ - G\ :sub:`33low bits 1--0`\ (bits 7--6) FG\ :sub:`32high bits 9--4`\ (bits 5--0)
+ * - start + 28:
+ - G\ :sub:`33high bits 9--2`
+ - R\ :sub:`34low bits 7--0`
+ - FG\ :sub:`35low bits 5--0`\ (bits 7--2) R\ :sub:`34high bits 9--8`\ (bits 1--0)
+ - FG\ :sub:`35high bits 3--0`
\ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr12.rst b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr12.rst
new file mode 100644
index 000000000000..cc888aac42c2
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr12.rst
@@ -0,0 +1,61 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-pix-fmt-mtisp-sbggr12:
+.. _v4l2-pix-fmt-mtisp-sgbrg12:
+.. _v4l2-pix-fmt-mtisp-sgrbg12:
+.. _v4l2-pix-fmt-mtisp-srggb12:
+
+*******************************
+V4L2_PIX_FMT_MTISP_SBGGR12 ('MBBC'), V4L2_PIX_FMT_MTISP_SGBRG12('MBGC'), V4L2_PIX_FMT_MTISP_SGRBG12('MBgC'), V4L2_PIX_FMT_MTISP_SRGGB12('MBRC')
+*******************************
+
+12-bit Packed Bayer formats.
+
+Description
+===========
+
+These four pixel formats are used by Mediatek ISP P1.
+This is a packed format, meaning all the data bits for a pixel lying
+next to each other with no padding in memory, with a depth of 12 bits per pixel.
+The least significant byte is stored at lower memory addresses (little-endian).
+The RGB byte order follows raw sRGB / Bayer format from sensor.
+They are conventionally described as GRGR... BGBG..., RGRG... GBGB..., etc.
+Below is an example of conventional RGB byte order BGGR.
+
+**Byte Order.**
+Each cell is one byte.
+
+pixels cross the byte boundary and have a ratio of 6 bytes for each 4 pixels.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - start + 0:
+ - B\ :sub:`00lowbits 7--0`
+ - G\ :sub:`01lowbits 3--0`\ (bits 7--4) B\ :sub:`00highbits 11--8`\ (bits 3--0)
+ - G\ :sub:`01highbits 7--0`
+ - B\ :sub:`02lowbits 7--0`
+ - G\ :sub:`03lowbits 3--0`\ (bits 7--4) B\ :sub:`02highbits 11--8`\ (bits 3--0)
+ - G\ :sub:`03highbits 7--0`
+ * - start + 6:
+ - G\ :sub:`10lowbits 7--0`
+ - R\ :sub:`11lowbits 3--0`\ (bits 7--4) G\ :sub:`10highbits 11--8`\ (bits 3--0)
+ - R\ :sub:`11highbits 7--0`
+ - G\ :sub:`12lowbits 7--0`
+ - R\ :sub:`13lowbits 3--0`\ (bits 7--4) G\ :sub:`12highbits 11--8`\ (bits 3--0)
+ - R\ :sub:`13highbits 7--0`
+ * - start + 12:
+ - B\ :sub:`20lowbits 7--0`
+ - G\ :sub:`21lowbits 3--0`\ (bits 7--4) B\ :sub:`20highbits 11--8`\ (bits 3--0)
+ - G\ :sub:`21highbits 7--0`
+ - B\ :sub:`22lowbits 7--0`
+ - G\ :sub:`23lowbits 3--0`\ (bits 7--4) B\ :sub:`22highbits 11--8`\ (bits 3--0)
+ - G\ :sub:`23highbits 7--0`
+ * - start + 18:
+ - G\ :sub:`30lowbits 7--0`
+ - R\ :sub:`31lowbits 3--0`\ (bits 7--4) G\ :sub:`30highbits 11--8`\ (bits 3--0)
+ - R\ :sub:`31highbits 7--0`
+ - G\ :sub:`32lowbits 7--0`
+ - R\ :sub:`33lowbits 3--0`\ (bits 7--4) G\ :sub:`32highbits 11--8`\ (bits 3--0)
+ - R\ :sub:`33highbits 7--0`
diff --git a/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr12f.rst b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr12f.rst
new file mode 100644
index 000000000000..c063de9f9ad8
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr12f.rst
@@ -0,0 +1,110 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-pix-fmt-mtisp-sbggr12f:
+.. _v4l2-pix-fmt-mtisp-sgbrg12f:
+.. _v4l2-pix-fmt-mtisp-sgrbg12f:
+.. _v4l2-pix-fmt-mtisp-srggb12f:
+
+*******************************
+V4L2_PIX_FMT_MTISP_SBGGR12F ('MFBC'), V4L2_PIX_FMT_MTISP_SGBRG12F('MFGC'), V4L2_PIX_FMT_MTISP_SGRBG12F('MFgC'), V4L2_PIX_FMT_MTISP_SRGGB12F('MFRC')
+*******************************
+
+12-bit Packed Full-G Bayer formats.
+
+Description
+===========
+
+These four pixel formats are used by Mediatek ISP P1.
+This is a packed format with a depth of 12 bits per sample with every 4 pixels.
+Full-G means 1 more pixel for green channel every 2 pixels.
+The least significant byte is stored at lower memory addresses (little-endian).
+The RGB byte order follows raw sRGB / Bayer format from sensor. They are conventionally
+described as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example of conventional
+RGB byte order BGGR.
+
+**Bit-packed representation.**
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - B\ :sub:`00`
+ - FG\ :sub:`01`
+ - G\ :sub:`02`
+ - B\ :sub:`03`
+ - FG\ :sub:`04`
+ - G\ :sub:`05`
+ * - G\ :sub:`10`
+ - R\ :sub:`11`
+ - FG\ :sub:`12`
+ - G\ :sub:`13`
+ - R\ :sub:`14`
+ - FG\ :sub:`15`
+
+**Byte Order.**
+Each cell is one byte.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - start + 0:
+ - B\ :sub:`00low bits 7--0`
+ - FG\ :sub:`01low bits 3--0`\ (bits 7--4) B\ :sub:`00high bits 11--8`\ (bits 3--0)
+ * - start + 2:
+ - FG\ :sub:`01high bits 7--0`
+ - G\ :sub:`02low bits 7--0`
+ * - start + 4:
+ - B\ :sub:`03low bits 3--0`\ (bits 7--4) G\ :sub:`02high bits 11--8`\ (bits 3--0)
+ - B\ :sub:`03high bits 7--0`
+ * - start + 6:
+ - FG\ :sub:`04low bits 7--0`
+ - G\ :sub:`05low bits 3--0`\ (bits 7--4) FG\ :sub:`04high bits 11--8`\ (bits 3--0)
+ * - start + 8:
+ - G\ :sub:`05high bits 7--0`
+ -
+ * - start + 10:
+ - G\ :sub:`10low bits 7--0`
+ - R\ :sub:`11low bits 3--0`\ (bits 7--4) G\ :sub:`10high bits 11--8`\ (bits 3--0)
+ * - start + 12:
+ - R\ :sub:`11high bits 7--0`
+ - FG\ :sub:`12low bits 7--0`
+ * - start + 14:
+ - G\ :sub:`13low bits 3--0`\ (bits 7--4) FG\ :sub:`12high bits 11--8`\ (bits 3--0)
+ - G\ :sub:`13high bits 7--0`
+ * - start + 16:
+ - R\ :sub:`14low bits 7--0`
+ - FG\ :sub:`15low bits 3--0`\ (bits 7--4) R\ :sub:`14high bits 11--8`\ (bits 3--0)
+ * - start + 18:
+ - FG\ :sub:`15high bits 7--0`
+ -
+ * - start + 20:
+ - B\ :sub:`20low bits 7--0`
+ - FG\ :sub:`21low bits 3--0`\ (bits 7--4) B\ :sub:`20high bits 11--8`\ (bits 3--0)
+ * - start + 22:
+ - FG\ :sub:`21high bits 7--0`
+ - G\ :sub:`22low bits 7--0`
+ * - start + 24:
+ - B\ :sub:`23low bits 3--0`\ (bits 7--4) G\ :sub:`22high bits 11--8`\ (bits 3--0)
+ - B\ :sub:`23high bits 7--0`
+ * - start + 26:
+ - FG\ :sub:`24low bits 7--0`
+ - G\ :sub:`25low bits 3--0`\ (bits 7--4) FG\ :sub:`24high bits 11--8`\ (bits 3--0)
+ * - start + 28:
+ - G\ :sub:`25high bits 7--0`
+ -
+ * - start + 30:
+ - G\ :sub:`30low bits 7--0`
+ - R\ :sub:`31low bits 3--0`\ (bits 7--4) G\ :sub:`30high bits 11--8`\ (bits 3--0)
+ * - start + 32:
+ - R\ :sub:`31high bits 7--0`
+ - FG\ :sub:`32low bits 7--0`
+ * - start + 34:
+ - G\ :sub:`33low bits 3--0`\ (bits 7--4) FG\ :sub:`32high bits 11--8`\ (bits 3--0)
+ - G\ :sub:`33high bits 7--0`
+ * - start + 36:
+ - R\ :sub:`34low bits 7--0`
+ - FG\ :sub:`35low bits 3--0`\ (bits 7--4) R\ :sub:`34high bits 11--8`\ (bits 3--0)
+ * - start + 38:
+ - FG\ :sub:`35high bits 7--0`
+ -
\ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr14.rst b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr14.rst
new file mode 100644
index 000000000000..39ea9882a792
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr14.rst
@@ -0,0 +1,73 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-pix-fmt-mtisp-sbggr14:
+.. _v4l2-pix-fmt-mtisp-sgbrg14:
+.. _v4l2-pix-fmt-mtisp-sgrbg14:
+.. _v4l2-pix-fmt-mtisp-srggb14:
+
+*******************************
+V4L2_PIX_FMT_MTISP_SBGGR14 ('MBBE'), V4L2_PIX_FMT_MTISP_SGBRG14('MBGE'), V4L2_PIX_FMT_MTISP_SGRBG14('MBgE'), V4L2_PIX_FMT_MTISP_SRGGB14('MBRE')
+*******************************
+
+14-bit Packed Bayer formats.
+
+Description
+===========
+
+These four pixel formats are used by Mediatek ISP P1.
+This is a packed format, meaning all the data bits for a pixel lying
+next to each other with no padding in memory, with a depth of 14 bits per pixel.
+The least significant byte is stored at lower memory addresses (little-endian).
+The RGB byte order follows raw sRGB / Bayer format from sensor.
+They are conventionally described as GRGR... BGBG..., RGRG... GBGB..., etc.
+Below is an example of conventional RGB byte order BGGR.
+
+**Byte Order.**
+Each cell is one byte.
+
+pixels cross the byte boundary and have a ratio of 7 bytes for each 4 pixels.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - start + 0:
+ - B\ :sub:`00low bits 7--0`
+ - G\ :sub:`01low bits 1--0`\ (bits 7--6) B\ :sub:`00high bits 13--8`\ (bits 5--0)
+ - G\ :sub:`01low bits 9--2`\
+ - B\ :sub:`02low bits 3--0`\ (bits 7--4) G\ :sub:`01high bits 13--10`\ (bits 3--0)
+ * - start + 4:
+ - B\ :sub:`02low bits 11--4`\
+ - G\ :sub:`03low bits 5--0`\ (bits 7--2) B\ :sub:`02high bits 13--12`\ (bits 1--0)
+ - G\ :sub:`03high bits 13--6`\
+ -
+ * - start + 8:
+ - G\ :sub:`10low bits 7--0`
+ - R\ :sub:`11low bits 1--0`\ (bits 7--6) G\ :sub:`10high bits 13--8`\ (bits 5--0)
+ - R\ :sub:`11low bits 9--2`\
+ - G\ :sub:`12low bits 3--0`\ (bits 7--4) R\ :sub:`11high bits 13--10`\ (bits 3--0)
+ * - start + 12:
+ - G\ :sub:`12low bits 11--4`\
+ - R\ :sub:`13low bits 5--0`\ (bits 7--2) G\ :sub:`12high bits 13--12`\ (bits 1--0)
+ - R\ :sub:`13high bits 13--6`\
+ -
+ * - start + 16:
+ - B\ :sub:`20low bits 7--0`
+ - G\ :sub:`21low bits 1--0`\ (bits 7--6) B\ :sub:`20high bits 13--8`\ (bits 5--0)
+ - G\ :sub:`21low bits 9--2`\
+ - B\ :sub:`22low bits 3--0`\ (bits 7--4) G\ :sub:`21high bits 13--10`\ (bits 3--0)
+ * - start + 20:
+ - B\ :sub:`22low bits 11--4`\
+ - G\ :sub:`23low bits 5--0`\ (bits 7--2) B\ :sub:`22high bits 13--12`\ (bits 1--0)
+ - G\ :sub:`23high bits 13--6`\
+ -
+ * - start + 24:
+ - G\ :sub:`30low bits 7--0`
+ - R\ :sub:`31low bits 1--0`\ (bits 7--6) G\ :sub:`30high bits 13--8`\ (bits 5--0)
+ - R\ :sub:`31low bits 9--2`\
+ - G\ :sub:`32low bits 3--0`\ (bits 7--4) R\ :sub:`31high bits 13--10`\ (bits 3--0)
+ * - start + 28:
+ - G\ :sub:`32low bits 11--4`\
+ - R\ :sub:`33low bits 5--0`\ (bits 7--2) G\ :sub:`32high bits 13--12`\ (bits 1--0)
+ - R\ :sub:`33high bits 13--6`\
+ -
\ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr14f.rst b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr14f.rst
new file mode 100644
index 000000000000..010b1c190c60
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr14f.rst
@@ -0,0 +1,110 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-pix-fmt-mtisp-sbggr14f:
+.. _v4l2-pix-fmt-mtisp-sgbrg14f:
+.. _v4l2-pix-fmt-mtisp-sgrbg14f:
+.. _v4l2-pix-fmt-mtisp-srggb14f:
+
+*******************************
+V4L2_PIX_FMT_MTISP_SBGGR14F ('MFBE'), V4L2_PIX_FMT_MTISP_SGBRG14F('MFGE'), V4L2_PIX_FMT_MTISP_SGRBG14F('MFgE'), V4L2_PIX_FMT_MTISP_SRGGB14F('MFRE')
+*******************************
+
+14-bit Packed Full-G Bayer formats.
+
+Description
+===========
+
+These four pixel formats are used by Mediatek ISP P1.
+This is a packed format with a depth of 14 bits per sample with every 4 pixels.
+Full-G means 1 more pixel for green channel every 2 pixels.
+The least significant byte is stored at lower memory addresses (little-endian).
+The RGB byte order follows raw sRGB / Bayer format from sensor. They are conventionally
+described as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example of conventional
+RGB byte order BGGR.
+
+**Bit-packed representation.**
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - B\ :sub:`00`
+ - FG\ :sub:`01`
+ - G\ :sub:`02`
+ - B\ :sub:`03`
+ - FG\ :sub:`04`
+ - G\ :sub:`05`
+ * - G\ :sub:`10`
+ - R\ :sub:`11`
+ - FG\ :sub:`12`
+ - G\ :sub:`13`
+ - R\ :sub:`14`
+ - FG\ :sub:`15`
+
+**Byte Order.**
+Each cell is one byte.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - start + 0:
+ - B\ :sub:`00low bits 7--0`
+ - FG\ :sub:`01low bits 1--0`\ (bits 7--6) B\ :sub:`00high bits 13--8`\ (bits 5--0)
+ - FG\ :sub:`01low bits 9--2`
+ - G\ :sub:`02low bits 3--0`\ (bits 7--4) FG\ :sub:`01high bits 13--10`\ (bits 3--0)
+ * - start + 4:
+ - G\ :sub:`02low bits 11--4`
+ - B\ :sub:`03low bits 5--0`\ (bits 7--2) G\ :sub:`02high bits 13--12`\ (bits 1--0)
+ - B\ :sub:`03high bits 13--6`
+ - FG\ :sub:`04low bits 7--0`
+ * - start + 8:
+ - G\ :sub:`05low bits 1--0`\ (bits 7--6) FG\ :sub:`04high bits 13--8`\ (bits 5--0)
+ - G\ :sub:`05high bits 9--2`
+ - G\ :sub:`05high bits 13--10`
+ -
+ * - start + 12:
+ - G\ :sub:`10low bits 7--0`
+ - R\ :sub:`11low bits 1--0`\ (bits 7--6) G\ :sub:`10high bits 13--8`\ (bits 5--0)
+ - R\ :sub:`11low bits 9--2`
+ - FG\ :sub:`12low bits 3--0`\ (bits 7--4) R\ :sub:`11high bits 13--10`\ (bits 3--0)
+ * - start + 16:
+ - FG\ :sub:`12low bits 11--4`
+ - G\ :sub:`13low bits 5--0`\ (bits 7--2) FG\ :sub:`12high bits 13--12`\ (bits 1--0)
+ - G\ :sub:`13high bits 13--6`
+ - R\ :sub:`14low bits 7--0`
+ * - start + 20:
+ - FG\ :sub:`15low bits 1--0`\ (bits 7--6) R\ :sub:`14high bits 13--8`\ (bits 5--0)
+ - FG\ :sub:`15high bits 9--2`
+ - FG\ :sub:`15high bits 13--10`
+ -
+ * - start + 24:
+ - B\ :sub:`20low bits 7--0`
+ - FG\ :sub:`21low bits 1--0`\ (bits 7--6) B\ :sub:`20high bits 13--8`\ (bits 5--0)
+ - FG\ :sub:`21low bits 9--2`
+ - G\ :sub:`22low bits 3--0`\ (bits 7--4) FG\ :sub:`21high bits 13--10`\ (bits 3--0)
+ * - start + 28:
+ - G\ :sub:`22low bits 11--4`
+ - B\ :sub:`23low bits 5--0`\ (bits 7--2) G\ :sub:`22high bits 13--12`\ (bits 1--0)
+ - B\ :sub:`23high bits 13--6`
+ - FG\ :sub:`24low bits 7--0`
+ * - start + 32:
+ - G\ :sub:`25low bits 1--0`\ (bits 7--6) FG\ :sub:`24high bits 13--8`\ (bits 5--0)
+ - G\ :sub:`25high bits 9--2`
+ - G\ :sub:`25high bits 13--10`
+ -
+ * - start + 36:
+ - G\ :sub:`30low bits 7--0`
+ - R\ :sub:`31low bits 1--0`\ (bits 7--6) G\ :sub:`30high bits 13--8`\ (bits 5--0)
+ - R\ :sub:`31low bits 9--2`
+ - FG\ :sub:`32low bits 3--0`\ (bits 7--4) R\ :sub:`31high bits 13--10`\ (bits 3--0)
+ * - start + 40:
+ - FG\ :sub:`32low bits 11--4`
+ - G\ :sub:`33low bits 5--0`\ (bits 7--2) FG\ :sub:`32high bits 13--12`\ (bits 1--0)
+ - G\ :sub:`33high bits 13--6`
+ - R\ :sub:`34low bits 7--0`
+ * - start + 44:
+ - FG\ :sub:`35low bits 1--0`\ (bits 7--6) R\ :sub:`34high bits 13--8`\ (bits 5--0)
+ - FG\ :sub:`35high bits 9--2`
+ - FG\ :sub:`35high bits 13--10`
+ -
\ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr8.rst b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr8.rst
new file mode 100644
index 000000000000..86cadbf38175
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr8.rst
@@ -0,0 +1,51 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-pix-fmt-mtisp-sbggr8:
+.. _v4l2-pix-fmt-mtisp-sgbrg8:
+.. _v4l2-pix-fmt-mtisp-sgrbg8:
+.. _v4l2-pix-fmt-mtisp-srggb8:
+
+*******************************
+V4L2_PIX_FMT_MTISP_SBGGR8 ('MBB8'), V4L2_PIX_FMT_MTISP_SGBRG8('MBG8'), V4L2_PIX_FMT_MTISP_SGRBG8('MBg8'), V4L2_PIX_FMT_MTISP_SRGGB8('MBR8')
+*******************************
+
+8-bit Packed Bayer formats.
+
+Description
+===========
+
+These four pixel formats are used by Mediatek ISP P1.
+This is a packed format, meaning all the data bits for a pixel lying
+next to each other with no padding in memory, with a depth of 8 bits per pixel.
+The least significant byte is stored at lower memory addresses (little-endian).
+The RGB byte order follows raw sRGB / Bayer format from sensor.
+They are conventionally described as GRGR... BGBG..., RGRG... GBGB..., etc.
+Below is an example of conventional RGB byte order BGGR.
+
+**Byte Order.**
+Each cell is one byte.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - start + 0:
+ - B\ :sub:`00`
+ - G\ :sub:`01`
+ - B\ :sub:`02`
+ - G\ :sub:`03`
+ * - start + 4:
+ - G\ :sub:`10`
+ - R\ :sub:`11`
+ - G\ :sub:`12`
+ - R\ :sub:`13`
+ * - start + 8:
+ - B\ :sub:`20`
+ - G\ :sub:`21`
+ - B\ :sub:`22`
+ - G\ :sub:`23`
+ * - start + 12:
+ - G\ :sub:`30`
+ - R\ :sub:`31`
+ - G\ :sub:`32`
+ - R\ :sub:`33`
\ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr8f.rst b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr8f.rst
new file mode 100644
index 000000000000..ca5151312bca
--- /dev/null
+++ b/Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr8f.rst
@@ -0,0 +1,78 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _v4l2-pix-fmt-mtisp-sbggr8f:
+.. _v4l2-pix-fmt-mtisp-sgbrg8f:
+.. _v4l2-pix-fmt-mtisp-sgrbg8f:
+.. _v4l2-pix-fmt-mtisp-srggb8f:
+
+*******************************
+V4L2_PIX_FMT_MTISP_SBGGR8F ('MFB8'), V4L2_PIX_FMT_MTISP_SGBRG8F('MFG8'), V4L2_PIX_FMT_MTISP_SGRBG8F('MFg8'), V4L2_PIX_FMT_MTISP_SRGGB8F('MFR8')
+*******************************
+
+8-bit Packed Full-G Bayer formats.
+
+Description
+===========
+
+These four pixel formats are used by Mediatek ISP P1.
+This is a packed format with a depth of 8 bits per sample with every 4 pixels.
+Full-G means 1 more pixel for green channel every 2 pixels.
+The least significant byte is stored at lower memory addresses (little-endian).
+The RGB byte order follows raw sRGB / Bayer format from sensor. They are conventionally
+described as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example of conventional
+RGB byte order BGGR.
+
+**Bit-packed representation.**
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - B\ :sub:`00`
+ - FG\ :sub:`01`
+ - G\ :sub:`02`
+ - B\ :sub:`03`
+ - FG\ :sub:`04`
+ - G\ :sub:`05`
+ * - G\ :sub:`10`
+ - R\ :sub:`11`
+ - FG\ :sub:`12`
+ - G\ :sub:`13`
+ - R\ :sub:`14`
+ - FG\ :sub:`15`
+
+**Byte Order.**
+Each cell is one byte.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+
+ * - start + 0:
+ - B\ :sub:`00`
+ - FG\ :sub:`01`
+ - G\ :sub:`02`
+ - B\ :sub:`03`
+ - FG\ :sub:`04`
+ - G\ :sub:`05`
+ * - start + 6:
+ - G\ :sub:`10`
+ - R\ :sub:`11`
+ - FG\ :sub:`12`
+ - G\ :sub:`13`
+ - R\ :sub:`14`
+ - FG\ :sub:`15`
+ * - start + 12:
+ - B\ :sub:`20`
+ - FG\ :sub:`21`
+ - G\ :sub:`22`
+ - B\ :sub:`23`
+ - FG\ :sub:`24`
+ - G\ :sub:`25`
+ * - start + 18:
+ - G\ :sub:`30`
+ - R\ :sub:`31`
+ - FG\ :sub:`32`
+ - G\ :sub:`33`
+ - R\ :sub:`34`
+ - FG\ :sub:`35`
\ No newline at end of file
diff --git a/Documentation/media/uapi/v4l/pixfmt-rgb.rst b/Documentation/media/uapi/v4l/pixfmt-rgb.rst
index 48ab80024835..1ba260c84083 100644
--- a/Documentation/media/uapi/v4l/pixfmt-rgb.rst
+++ b/Documentation/media/uapi/v4l/pixfmt-rgb.rst
@@ -28,3 +28,11 @@ RGB Formats
pixfmt-srggb12p
pixfmt-srggb14p
pixfmt-srggb16
+ pixfmt-pixfmt-mtisp-srggb8
+ pixfmt-pixfmt-mtisp-srggb10
+ pixfmt-pixfmt-mtisp-srggb12
+ pixfmt-pixfmt-mtisp-srggb14
+ pixfmt-pixfmt-mtisp-srggb8f
+ pixfmt-pixfmt-mtisp-srggb10f
+ pixfmt-pixfmt-mtisp-srggb12f
+ pixfmt-pixfmt-mtisp-srggb14f
\ No newline at end of file
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index b1f4b991dba6..451dada2146d 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1293,6 +1293,38 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_KONICA420: descr = "GSPCA KONICA420"; break;
case V4L2_PIX_FMT_HSV24: descr = "24-bit HSV 8-8-8"; break;
case V4L2_PIX_FMT_HSV32: descr = "32-bit XHSV 8-8-8-8"; break;
+ case V4L2_PIX_FMT_MTISP_SBGGR8: descr = "8-bit Bayer BGGR MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGBRG8: descr = "8-bit Bayer GBRG MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGRBG8: descr = "8-bit Bayer GRBG MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SRGGB8: descr = "8-bit Bayer RGGB MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SBGGR10: descr = "10-bit Bayer BGGR MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGBRG10: descr = "10-bit Bayer GBRG MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGRBG10: descr = "10-bit Bayer GRBG MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SRGGB10: descr = "10-bit Bayer RGGB MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SBGGR12: descr = "12-bit Bayer BGGR MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGBRG12: descr = "12-bit Bayer GBRG MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGRBG12: descr = "12-bit Bayer GRBG MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SRGGB12: descr = "12-bit Bayer RGGB MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SBGGR14: descr = "14-bit Bayer BGGR MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGBRG14: descr = "14-bit Bayer GBRG MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGRBG14: descr = "14-bit Bayer GRBG MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SRGGB14: descr = "14-bit Bayer RGGB MTISP Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SBGGR8F: descr = "8-bit Full-G Bayer BGGR Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGBRG8F: descr = "8-bit Full-G Bayer GBRG Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGRBG8F: descr = "8-bit Full-G Bayer GRBG Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SRGGB8F: descr = "8-bit Full-G Bayer RGGB Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SBGGR10F: descr = "10-bit Full-G Bayer BGGR Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGBRG10F: descr = "10-bit Full-G Bayer GBRG Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGRBG10F: descr = "10-bit Full-G Bayer GRBG Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SRGGB10F: descr = "10-bit Full-G Bayer RGGB Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SBGGR12F: descr = "12-bit Full-G Bayer BGGR Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGBRG12F: descr = "12-bit Full-G Bayer GBRG Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGRBG12F: descr = "12-bit Full-G Bayer GRBG Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SRGGB12F: descr = "12-bit Full-G Bayer RGGB Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SBGGR14F: descr = "14-bit Full-G Bayer BGGR Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGBRG14F: descr = "14-bit Full-G Bayer GBRG Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SGRBG14F: descr = "14-bit Full-G Bayer GRBG Packed"; break;
+ case V4L2_PIX_FMT_MTISP_SRGGB14F: descr = "14-bit Full-G Bayer RGGB Packed"; break;
case V4L2_SDR_FMT_CU8: descr = "Complex U8"; break;
case V4L2_SDR_FMT_CU16LE: descr = "Complex U16LE"; break;
case V4L2_SDR_FMT_CS8: descr = "Complex S8"; break;
@@ -1308,6 +1340,11 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_META_FMT_VSP1_HGO: descr = "R-Car VSP1 1-D Histogram"; break;
case V4L2_META_FMT_VSP1_HGT: descr = "R-Car VSP1 2-D Histogram"; break;
case V4L2_META_FMT_UVC: descr = "UVC payload header metadata"; break;
+ case V4L2_META_FMT_MTISP_3A: descr = "AE/AWB Histogram"; break;
+ case V4L2_META_FMT_MTISP_AF: descr = "AF Histogram"; break;
+ case V4L2_META_FMT_MTISP_LCS: descr = "Local Contrast Enhancement Stat"; break;
+ case V4L2_META_FMT_MTISP_LMV: descr = "Local Motion Vector Histogram"; break;
+ case V4L2_META_FMT_MTISP_PARAMS: descr = "MTK ISP Tuning Metadata"; break;
default:
/* Compressed formats */
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 9d9705ceda76..8eabcd6a97bc 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -728,6 +728,40 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_IPU3_SGRBG10 v4l2_fourcc('i', 'p', '3', 'G') /* IPU3 packed 10-bit GRBG bayer */
#define V4L2_PIX_FMT_IPU3_SRGGB10 v4l2_fourcc('i', 'p', '3', 'r') /* IPU3 packed 10-bit RGGB bayer */
+/* Vendor specific - Mediatek ISP bayer formats */
+#define V4L2_PIX_FMT_MTISP_SBGGR8 v4l2_fourcc('M', 'B', 'B', '8') /* Packed 8-bit */
+#define V4L2_PIX_FMT_MTISP_SGBRG8 v4l2_fourcc('M', 'B', 'G', '8') /* Packed 8-bit */
+#define V4L2_PIX_FMT_MTISP_SGRBG8 v4l2_fourcc('M', 'B', 'g', '8') /* Packed 8-bit */
+#define V4L2_PIX_FMT_MTISP_SRGGB8 v4l2_fourcc('M', 'B', 'R', '8') /* Packed 8-bit */
+#define V4L2_PIX_FMT_MTISP_SBGGR10 v4l2_fourcc('M', 'B', 'B', 'A') /* Packed 10-bit */
+#define V4L2_PIX_FMT_MTISP_SGBRG10 v4l2_fourcc('M', 'B', 'G', 'A') /* Packed 10-bit */
+#define V4L2_PIX_FMT_MTISP_SGRBG10 v4l2_fourcc('M', 'B', 'g', 'A') /* Packed 10-bit */
+#define V4L2_PIX_FMT_MTISP_SRGGB10 v4l2_fourcc('M', 'B', 'R', 'A') /* Packed 10-bit */
+#define V4L2_PIX_FMT_MTISP_SBGGR12 v4l2_fourcc('M', 'B', 'B', 'C') /* Packed 12-bit */
+#define V4L2_PIX_FMT_MTISP_SGBRG12 v4l2_fourcc('M', 'B', 'G', 'C') /* Packed 12-bit */
+#define V4L2_PIX_FMT_MTISP_SGRBG12 v4l2_fourcc('M', 'B', 'g', 'C') /* Packed 12-bit */
+#define V4L2_PIX_FMT_MTISP_SRGGB12 v4l2_fourcc('M', 'B', 'R', 'C') /* Packed 12-bit */
+#define V4L2_PIX_FMT_MTISP_SBGGR14 v4l2_fourcc('M', 'B', 'B', 'E') /* Packed 14-bit */
+#define V4L2_PIX_FMT_MTISP_SGBRG14 v4l2_fourcc('M', 'B', 'G', 'E') /* Packed 14-bit */
+#define V4L2_PIX_FMT_MTISP_SGRBG14 v4l2_fourcc('M', 'B', 'g', 'E') /* Packed 14-bit */
+#define V4L2_PIX_FMT_MTISP_SRGGB14 v4l2_fourcc('M', 'B', 'R', 'E') /* Packed 14-bit */
+#define V4L2_PIX_FMT_MTISP_SBGGR8F v4l2_fourcc('M', 'F', 'B', '8') /* Full-G 8-bit */
+#define V4L2_PIX_FMT_MTISP_SGBRG8F v4l2_fourcc('M', 'F', 'G', '8') /* Full-G 8-bit */
+#define V4L2_PIX_FMT_MTISP_SGRBG8F v4l2_fourcc('M', 'F', 'g', '8') /* Full-G 8-bit */
+#define V4L2_PIX_FMT_MTISP_SRGGB8F v4l2_fourcc('M', 'F', 'R', '8') /* Full-G 8-bit */
+#define V4L2_PIX_FMT_MTISP_SBGGR10F v4l2_fourcc('M', 'F', 'B', 'A') /* Full-G 10-bit */
+#define V4L2_PIX_FMT_MTISP_SGBRG10F v4l2_fourcc('M', 'F', 'G', 'A') /* Full-G 10-bit */
+#define V4L2_PIX_FMT_MTISP_SGRBG10F v4l2_fourcc('M', 'F', 'g', 'A') /* Full-G 10-bit */
+#define V4L2_PIX_FMT_MTISP_SRGGB10F v4l2_fourcc('M', 'F', 'R', 'A') /* Full-G 10-bit */
+#define V4L2_PIX_FMT_MTISP_SBGGR12F v4l2_fourcc('M', 'F', 'B', 'C') /* Full-G 12-bit */
+#define V4L2_PIX_FMT_MTISP_SGBRG12F v4l2_fourcc('M', 'F', 'G', 'C') /* Full-G 12-bit */
+#define V4L2_PIX_FMT_MTISP_SGRBG12F v4l2_fourcc('M', 'F', 'g', 'C') /* Full-G 12-bit */
+#define V4L2_PIX_FMT_MTISP_SRGGB12F v4l2_fourcc('M', 'F', 'R', 'C') /* Full-G 12-bit */
+#define V4L2_PIX_FMT_MTISP_SBGGR14F v4l2_fourcc('M', 'F', 'B', 'E') /* Full-G 14-bit */
+#define V4L2_PIX_FMT_MTISP_SGBRG14F v4l2_fourcc('M', 'F', 'G', 'E') /* Full-G 14-bit */
+#define V4L2_PIX_FMT_MTISP_SGRBG14F v4l2_fourcc('M', 'F', 'g', 'E') /* Full-G 14-bit */
+#define V4L2_PIX_FMT_MTISP_SRGGB14F v4l2_fourcc('M', 'F', 'R', 'E') /* Full-G 14-bit */
+
/* SDR formats - used only for Software Defined Radio devices */
#define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */
#define V4L2_SDR_FMT_CU16LE v4l2_fourcc('C', 'U', '1', '6') /* IQ u16le */
@@ -749,6 +783,11 @@ struct v4l2_pix_format {
#define V4L2_META_FMT_VSP1_HGT v4l2_fourcc('V', 'S', 'P', 'T') /* R-Car VSP1 2-D Histogram */
#define V4L2_META_FMT_UVC v4l2_fourcc('U', 'V', 'C', 'H') /* UVC Payload Header metadata */
#define V4L2_META_FMT_D4XX v4l2_fourcc('D', '4', 'X', 'X') /* D4XX Payload Header metadata */
+#define V4L2_META_FMT_MTISP_3A v4l2_fourcc('M', 'T', 'f', 'a') /* AE/AWB histogram */
+#define V4L2_META_FMT_MTISP_AF v4l2_fourcc('M', 'T', 'f', 'f') /* AF histogram */
+#define V4L2_META_FMT_MTISP_LCS v4l2_fourcc('M', 'T', 'f', 'c') /* Local contrast enhanced statistics */
+#define V4L2_META_FMT_MTISP_LMV v4l2_fourcc('M', 'T', 'f', 'm') /* Local motion vector histogram */
+#define V4L2_META_FMT_MTISP_PARAMS v4l2_fourcc('M', 'T', 'f', 'p') /* ISP tuning parameters */
/* priv field value to indicates that subsequent fields are valid. */
#define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe
--
2.18.0
^ permalink raw reply related
* [RFC,v4,2/4] dts: arm64: mt8183: Add ISP Pass 1 nodes
From: Jungo Lin @ 2019-08-07 12:48 UTC (permalink / raw)
To: tfiga, hverkuil-cisco, laurent.pinchart, matthias.bgg, mchehab
Cc: shik, devicetree, Sean.Cheng, suleiman, Rynn.Wu, srv_heupstream,
robh, ryan.yu, Jerry-ch.Chen, frankie.chiu, jungo.lin, sj.huang,
yuzhao, linux-mediatek, zwisler, ddavenport, frederic.chen,
linux-arm-kernel, linux-media
In-Reply-To: <20190807124803.29884-1-jungo.lin@mediatek.com>
Add nodes for Pass 1 unit of Mediatek's camera ISP system.
Pass 1 unit embedded in Mediatek SoCs, works with the
co-processor to process image signal from the image sensor
and output RAW image data.
Signed-off-by: Jungo Lin <jungo.lin@mediatek.com>
---
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 31 ++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index 111866d36862..1692466c62fc 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -487,6 +487,37 @@
#clock-cells = <1>;
};
+ camisp: camisp@1a000000 {
+ compatible = "mediatek,mt8183-camisp", "syscon";
+ reg = <0 0x1a000000 0 0x1000>,
+ <0 0x1a003000 0 0x1000>,
+ <0 0x1a004000 0 0x2000>,
+ <0 0x1a006000 0 0x2000>,
+ <0 0x1a008000 0 0x2000>;
+ reg-names = "cam_sys",
+ "cam_uni",
+ "cam_a",
+ "cam_b",
+ "cam_c";
+ interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 254 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 255 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 256 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "cam_uni",
+ "cam_a",
+ "cam_b",
+ "cam_c";
+ iommus = <&iommu M4U_PORT_CAM_IMGO>;
+ clocks = <&camsys CLK_CAM_CAM>,
+ <&camsys CLK_CAM_CAMTG>;
+ clock-names = "camsys_cam_cgpdn",
+ "camsys_camtg_cgpdn";
+ mediatek,larb = <&larb3>,
+ <&larb6>;
+ power-domains = <&scpsys MT8183_POWER_DOMAIN_CAM>;
+ mediatek,scp = <&scp>;
+ };
+
larb6: larb@1a001000 {
compatible = "mediatek,mt8183-smi-larb";
reg = <0 0x1a001000 0 0x1000>;
--
2.18.0
^ permalink raw reply related
* [RFC,v4,1/4] media: dt-bindings: mt8183: Added camera ISP Pass 1
From: Jungo Lin @ 2019-08-07 12:48 UTC (permalink / raw)
To: tfiga, hverkuil-cisco, laurent.pinchart, matthias.bgg, mchehab
Cc: shik, devicetree, Sean.Cheng, suleiman, Rynn.Wu, srv_heupstream,
robh, ryan.yu, Jerry-ch.Chen, frankie.chiu, jungo.lin, sj.huang,
yuzhao, linux-mediatek, zwisler, ddavenport, frederic.chen,
linux-arm-kernel, linux-media
In-Reply-To: <20190807124803.29884-1-jungo.lin@mediatek.com>
This patch adds DT binding document for the Pass 1 (P1) unit
in Mediatek's camera ISP system. The Pass 1 unit grabs the sensor
data out from the sensor interface, applies ISP image effects
from tuning data and outputs the image data or statistics data to DRAM.
Signed-off-by: Jungo Lin <jungo.lin@mediatek.com>
---
.../bindings/media/mediatek,camisp.txt | 73 +++++++++++++++++++
1 file changed, 73 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/mediatek,camisp.txt
diff --git a/Documentation/devicetree/bindings/media/mediatek,camisp.txt b/Documentation/devicetree/bindings/media/mediatek,camisp.txt
new file mode 100644
index 000000000000..fa2713acceca
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/mediatek,camisp.txt
@@ -0,0 +1,73 @@
+* Mediatek Image Signal Processor Pass 1 (ISP P1)
+
+The Pass 1 unit of Mediatek's camera ISP system grabs the sensor data out
+from the sensor interface, applies ISP effects from tuning data and outputs
+the image data and statistics data to DRAM. Furthermore, Pass 1 unit has
+the ability to output two different resolutions frames at the same time to
+increase the performance of the camera application.
+
+Required properties:
+- compatible: Must be "mediatek,mt8183-camisp" for MT8183.
+- reg: Physical base address of the camera function block register and
+ length of memory mapped region. Must contain an entry for each entry
+ in reg-names.
+- reg-names: Must include the following entries:
+ "cam_sys": Camera base function block
+ "cam_uni": Camera UNI function block
+ "cam_a": Camera ISP P1 hardware unit A
+ "cam_b": Camera ISP P1 hardware unit B
+ "cam_c": Camera ISP P1 hardware unit C
+- interrupts: Must contain an entry for each entry in interrupt-names.
+- interrupt-names : Must include the following entries:
+ "cam_uni": Camera UNI interrupt
+ "cam_a": Camera unit A interrupt
+ "cam_b": Camera unit B interrupt
+ "cam_c": Camera unit C interrupt
+- iommus: Shall point to the respective IOMMU block with master port
+ as argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+ for details.
+- clocks: A list of phandle and clock specifier pairs as listed
+ in clock-names property, see
+ Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
+- clock-names: Must be "camsys_cam_cgpdn" and "camsys_camtg_cgpdn".
+- mediatek,larb: Must contain the local arbiters in the current SoCs, see
+ Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
+ for details.
+- power-domains: a phandle to the power domain, see
+ Documentation/devicetree/bindings/power/power_domain.txt for details.
+- mediatek,scp : The node of system control processor (SCP), see
+ Documentation/devicetree/bindings/remoteproc/mtk,scp.txt for details.
+
+Example:
+SoC specific DT entry:
+
+ camisp: camisp@1a000000 {
+ compatible = "mediatek,mt8183-camisp", "syscon";
+ reg = <0 0x1a000000 0 0x1000>,
+ <0 0x1a003000 0 0x1000>,
+ <0 0x1a004000 0 0x2000>,
+ <0 0x1a006000 0 0x2000>,
+ <0 0x1a008000 0 0x2000>;
+ reg-names = "cam_sys",
+ "cam_uni",
+ "cam_a",
+ "cam_b",
+ "cam_c";
+ interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 254 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 255 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 256 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "cam_uni",
+ "cam_a",
+ "cam_b",
+ "cam_c";
+ iommus = <&iommu M4U_PORT_CAM_IMGO>;
+ clocks = <&camsys CLK_CAM_CAM>,
+ <&camsys CLK_CAM_CAMTG>;
+ clock-names = "camsys_cam_cgpdn",
+ "camsys_camtg_cgpdn";
+ mediatek,larb = <&larb3>,
+ <&larb6>;
+ power-domains = <&scpsys MT8183_POWER_DOMAIN_CAM>;
+ mediatek,scp = <&scp>;
+ };
--
2.18.0
^ permalink raw reply related
* [RFC, v4, 0/4] media: platform: mtk-isp: Add Mediatek ISP Pass 1 driver
From: Jungo Lin @ 2019-08-07 12:47 UTC (permalink / raw)
To: tfiga, hverkuil-cisco, laurent.pinchart, matthias.bgg, mchehab
Cc: shik, devicetree, Sean.Cheng, suleiman, Rynn.Wu, srv_heupstream,
robh, ryan.yu, Jerry-ch.Chen, frankie.chiu, jungo.lin, sj.huang,
yuzhao, linux-mediatek, zwisler, ddavenport, frederic.chen,
linux-arm-kernel, linux-media
In-Reply-To: <Jungo Lin <jungo.lin@mediatek.com>
Hello,
This RFC patch series adding the driver for Pass 1 (P1) unit in
Mediatek's camera ISP system on mt8183 SoC, which will be used in
camera features of CrOS. It's the first time Mediatek develops
ISP kernel drivers based on V4L2 and media controller framework.
I posted the main part of the ISP Pass 1 driver as RFC to discuss
first and would like some review comments on the overall architecture
of the driver.
Pass 1 unit processes image signal from sensor devices and accepts the
tuning parameters to adjust the image quality. It performs optical
black correction, defect pixel correction, W/IR imbalance correction
and lens shading correction for RAW processing.
The driver is implemented with V4L2 and media controller framework so
we have the following entities to describe the ISP pass 1 path.
(The current metadata interface used in meta input and partial meta
nodes is only a temporary solution to kick off the driver development
and is not ready to be reviewed yet.)
1. meta input (output video device): connect to ISP P1 sub device.
It accepts the tuning buffer from user.
2. ISP P1 (sub device): connect to partial meta 0/1/2/3,
main stream and packed out video devices. When processing an image,
Pass 1 hardware supports multiple output images with different sizes
and formats so it needs two capture video devices ("main stream" and
"packed out") to return the image data to the user.
3. main stream (capture video device): return the processed image data
which is used in capture scenario.
4. packed out (capture video device): return the processed image data
which is used in preview scenario.
5. partial meta 0 (capture video device): return the AE/AWB statistics.
6. partial meta 1 (capture video device): return the AF statistics.
7. partial meta 2 (capture video device): return the local contrast
enhanced statistics.
8. partial meta 3 (capture video device): return the local motion
vector statistics.
The overall patches of the series is:
* Patch 1 & 2 are dt-bindings & dts information related to ISP P1 driver.
* Patch 3 extends the original V4L2 image & meta formats for ISP P1 driver.
* Patch 4 is the heart of ISP P1 driver. It handles the ISP
HW configuration. Moreover, implement standard V4L2 video driver that utilizes
V4L2 and media framework APIs. Communicate with co-process via SCP communication
to compose ISP registers in the firmware.
Here is ISP P1 media topology:
It is included the main/sub sensor & sen-inf sub-devices which are implemented
in below patch[1][2][3]:
For Mediatek ISP P1 driver, it also depends on MT8183 SCP[6] & IOMMU[7] patchsets
/usr/bin/media-ctl -p -d /dev/media1
Media controller API version 4.19.59
Media device information
------------------------
driver mtk-cam-p1
model mtk-cam-p1
serial
bus info platform:1a000000.camisp
hw revision 0x0
driver version 4.19.59
Device topology
- entity 1: mtk-cam-p1 (12 pads, 8 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev5
pad0: Sink
<- "mtk-cam-p1 meta input":0 []
pad1: Source
-> "mtk-cam-p1 main stream":0 [ENABLED,IMMUTABLE]
pad2: Source
-> "mtk-cam-p1 packed out":0 []
pad3: Source
-> "mtk-cam-p1 partial meta 0":0 []
pad4: Source
-> "mtk-cam-p1 partial meta 1":0 []
pad5: Source
-> "mtk-cam-p1 partial meta 2":0 []
pad6: Source
-> "mtk-cam-p1 partial meta 3":0 []
pad7: Source
pad8: Source
pad9: Source
pad10: Source
pad11: Sink
<- "1a040000.seninf.mipi-csi":4 [ENABLED,IMMUTABLE]
- entity 14: mtk-cam-p1 meta input (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video25
pad0: Source
-> "mtk-cam-p1":0 []
- entity 20: mtk-cam-p1 main stream (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video26
pad0: Sink
<- "mtk-cam-p1":1 [ENABLED,IMMUTABLE]
- entity 26: mtk-cam-p1 packed out (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video27
pad0: Sink
<- "mtk-cam-p1":2 []
- entity 32: mtk-cam-p1 partial meta 0 (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video28
pad0: Sink
<- "mtk-cam-p1":3 []
- entity 38: mtk-cam-p1 partial meta 1 (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video29
pad0: Sink
<- "mtk-cam-p1":4 []
- entity 44: mtk-cam-p1 partial meta 2 (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video30
pad0: Sink
<- "mtk-cam-p1":5 []
- entity 50: mtk-cam-p1 partial meta 3 (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video31
pad0: Sink
<- "mtk-cam-p1":6 []
- entity 56: 1a040000.seninf.mipi-csi (12 pads, 3 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev6
pad0: Sink
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
<- "ov5695 2-0036":0 []
pad1: Sink
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
<- "ov2685 4-003c":0 []
pad2: Sink
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
pad3: Sink
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
pad4: Source
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
-> "mtk-cam-p1":11 [ENABLED,IMMUTABLE]
pad5: Source
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
pad6: Source
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
pad7: Source
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
pad8: Source
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
pad9: Source
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
pad10: Source
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
pad11: Source
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
- entity 69: ov5695 2-0036 (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev7
pad0: Source
[fmt:SBGGR10_1X10/2592x1944 field:none colorspace:srgb]
-> "1a040000.seninf.mipi-csi":0 []
- entity 73: ov2685 4-003c (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev8
pad0: Source
[fmt:SBGGR10_1X10/1600x1200 field:none colorspace:srgb]
-> "1a040000.seninf.mipi-csi":1 []
===========
= history =
===========
version 4:
- Fix Tomasz's comments which are addressed in MTK ISP P1 driver v3 patch[4]
- Fix some Tomasz comments which are addressed in DIP's v2 patch[5]
- Extend MTK proprietary image formats to support bayer order
- Support V4L2_BUF_FLAG_TSTAMP_SRC_SOE for capture devices
Todo:
- vb2_ops's buf_request_complete callback function implementation
- Add rst documents for Mediatek meta formats
- New meta buffer structure design & re-factoring
- Support V4L2_BUF_FLAG_TIMESTAMP_BOOTTIME timestamp flag
- Align and pack IPI comamnd structures for EC ROM size shrink
version 3:
- Remove ISP Pass 1 reserved memory device node and change to use SCP's
reserved memory region. (Rob Herring)
- Fix comments of ISP Pass 1 device node & dt-bindings document (Rob Herring)
- Revise ISP Pass1 Kconfig
- Add rst documents for Mediatek image formats (Hans Verkuil)
- Fix kernel warning messages when running v4l2_compliance test
- Move AFO buffer enqueue & de-queue from request API to non-request
- mtk_cam-ctrl.h/mtk_cam-ctrl.c
Revise Mediatek ISP Pass1 specific V4L2 control naming & file licence declaration (Hans Verkuil)
Split GET_BIN_INFO control into two controls to get width & height in-dependently (Hans Verkuil)
- mtk_cam-v4l2-util.h/mtk_cam-v4l2-util.c
Merging mtk_cam-dev.c and mtk_cam-v4l2-util.c. (Drew Davenport)
Remove the pix_mode argument in related functions and unreachable code. (Drew Davenport)
Fix Drew's comments which are addressed in v2 patch
Fix some Tomasz comments which are addressed in DIP's v1 patch[3]
- mtk_cam-regs.h / mtk_cam.h / mtk_cam.c
Fix Drew's comments which are addressed in v2 patch
Fix some Tomasz comments which are addressed in DIP's v1 patch[3]
Refactoring mtk_isp_config & mtk_isp_req_enqueue functions
- mtk_cam-scp.h / mtk_cam-scp.c
Move function declarations from mtk_cam.h to mtk_cam-scp.h (Drew Davenport)
Fix some Tomasz comments which are addressed in DIP's v1 patch[3]
Fix ISP de-initialize timing KE issue
- mtk_cam-smem.h / mtk_cam-smem-dev.c
Get the reserved shared memory via SCP driver (Tomasz Figa)
Todo:
- Add rst documents for Mediatek meta formats
- New meta buffer structure design & re-factoring
version 2:
- Add 3A enhancement feature which includes:
Separates 3A pipeline out of frame basis to improve
AE/AWB (exposure and white balance) performance.
Add 2 SCP sub-commands for 3A meta buffers.
- Add new child device to manage P1 shared memory between P1 HW unit
and co-processor.
- Remove mediatek,cam_smem.txt & cam_smem dts node in mt8183.dtsi.
- Revised document wording for dt-bindings documents & dts information.
- Remove mtk_cam-ctx.h & mtk_cam-dev-ctx-core.c and move these
source codes to mtk_cam-dev.h & mtk_cam-dev.c.
- mtk_cam-dev.h / mtk_cam-dev.c
Revised mtk_cam_video_device & mtk_cam_dev to remove unused structure fields
or add comments.
Revised buffer size for LMVO & LCSO.
Fix pixel format utility function.
Add vb2_dma_contig_set_max_seg_size to configure DMA max segment size.
- mtk_cam-v4l2-util.c
Refactoring V4L2 async mechanism with seninf driver only
Refactoring CIO (Connection IO) implementation with active sensor
Revised stream on function for 3A enhancement feature
Add new V4L2 en-queue/de-queue utility functions for 3A enhancement feature
- mtk_cam-regs.h / mtk_cam.h / mtk_cam.c
Add meta buffer index register definitions
Add meta DMA configuration function.
Separate with frame-base and non-frame-base en-queue/de-queue functions
Add isp_setup_scp_rproc function to get RPC handle
Add mtk_cam_reserved_memory_init for shared memory management
- mtk_cam-scp.h / mtk_cam-scp.c
Add new meta strictures for 3A enhancement feature
Add new IPI command utility function for 3A enhancement feature
Enhance isp_composer_dma_sg_init function flow
Shorten overall IPI command structure size
Remove scp_state state checking
Improve code readability
- mtk_cam-smem.h / mtk_cam-smem-dev.c
Add mtk_cam_alloc_smem_dev to allocate one new child device of ISP driver.
Handling P1 driver 's reserved memory & allocate DMA buffers based on this
memory region.
TODOs:
- 3A enhancement feature bug fixing
version 1:
- Revised driver sources based on Tomasz's comments including
part1/2/3/4 in RFC V0 patch.
- Remove DMA cache mechanism.
Support two new video devices (LCSO/LMVO) for advance camera
features.
- Fixed v4l2-compliance test failure items.
- Add private controls for Mediatek camera middle-ware.
- Replace VPU driver's APIs with new SCP driver interface for
co-processor communication.
- Refactoring mtk_cam_scp.c to use ring-buffers mechanism for IPI
commands RX handling.
- Fix internal bugs.
TODOs:
- Remove mtk_cam_smem_drv.c & mtk_cam_smem.h and implement DMA pool
for shared memory management.
- Revised file names.
- Support non frame-sync AFO/AAO DMA buffers
version 0:
- Initial submission
==================
Dependent patch
==================
Camera ISP P1 driver depends on seninf driver, SCP driver.
The patches are listed as following:
[1]. BACKPORT: FROMLIST: platform: mtk-isp: Add Mediatek sensor interface driver
https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1482517
[2]. WIP: media: ov5695: support ov5695 sensor in mt8183
https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1614887
[3]. WIP: media: ov2685: support ov2685 sensor in mt8183
https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1614885
[4]. media: platform: mtk-isp: Add Mediatek ISP Pass 1 driver
https://patchwork.linuxtv.org/cover/56778/
[5]. [RFC,V2,4/6] platform: mtk-isp: Add Mediatek DIP driver
https://patchwork.linuxtv.org/patch/57472/
[6]. Add support for mt8183 SCP
https://patchwork.kernel.org/cover/11076543/
[7]. MT8183 IOMMU SUPPORT
https://patchwork.kernel.org/cover/10984739/
==================
Compliance test
==================
The v4l2-compliance is built with the below lastest patch.
https://git.linuxtv.org/v4l-utils.git/commit/?id=28be49b4e9d72c5866188cf5ba408541c665c921
Note 1.
This testing depends on the above seninf & sensors patches[1][2][3].
Note 2.
The current failure items are related to Mediatek seninf driver which
is under developing in other patchset.[1]
/usr/bin/v4l2-compliance -m /dev/media1
v4l2-compliance SHA: not available, 32 bits
Compliance test for mtk-cam-p1 device /dev/media1:
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Required ioctls:
test MEDIA_IOC_DEVICE_INFO: OK
Allow for multiple opens:
test second /dev/media1 open: OK
test MEDIA_IOC_DEVICE_INFO: OK
test for unlimited opens: OK
Media Controller ioctls:
test MEDIA_IOC_G_TOPOLOGY: OK
Entities: 11 Interfaces: 11 Pads: 33 Links: 21
test MEDIA_IOC_ENUM_ENTITIES/LINKS: OK
test MEDIA_IOC_SETUP_LINK: OK
Total for mtk-cam-p1 device /dev/media1: 7, Succeeded: 7, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-cam-p1 device /dev/video25:
Driver Info:
Driver name : mtk-cam-p1
Card type : mtk-cam-p1
Bus info : platform:1a000000.camisp
Driver version : 4.19.59
Capabilities : 0x8c200000
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x0c200000
Streaming
Extended Pix Format
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Interface Info:
ID : 0x03000010
Type : V4L Video
Entity Info:
ID : 0x0000000e (14)
Name : mtk-cam-p1 meta input
Function : V4L2 I/O
Pad 0x0100000f : 0: Source
Link 0x02000012: to remote pad 0x1000002 of entity 'mtk-cam-p1': Data
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second /dev/video25 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK
test Requests: OK
Total for mtk-cam-p1 device /dev/video25: 45, Succeeded: 45, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-cam-p1 device /dev/video26:
Driver Info:
Driver name : mtk-cam-p1
Card type : mtk-cam-p1
Bus info : platform:1a000000.camisp
Driver version : 4.19.59
Capabilities : 0x84201000
Video Capture Multiplanar
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04201000
Video Capture Multiplanar
Streaming
Extended Pix Format
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Interface Info:
ID : 0x03000016
Type : V4L Video
Entity Info:
ID : 0x00000014 (20)
Name : mtk-cam-p1 main stream
Function : V4L2 I/O
Pad 0x01000015 : 0: Sink
Link 0x02000018: from remote pad 0x1000003 of entity 'mtk-cam-p1': Data, Enabled, Immutable
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second /dev/video26 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK
test Requests: OK
Total for mtk-cam-p1 device /dev/video26: 45, Succeeded: 45, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-cam-p1 device /dev/video27:
Driver Info:
Driver name : mtk-cam-p1
Card type : mtk-cam-p1
Bus info : platform:1a000000.camisp
Driver version : 4.19.59
Capabilities : 0x84201000
Video Capture Multiplanar
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04201000
Video Capture Multiplanar
Streaming
Extended Pix Format
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Interface Info:
ID : 0x0300001c
Type : V4L Video
Entity Info:
ID : 0x0000001a (26)
Name : mtk-cam-p1 packed out
Function : V4L2 I/O
Pad 0x0100001b : 0: Sink
Link 0x0200001e: from remote pad 0x1000004 of entity 'mtk-cam-p1': Data
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second /dev/video27 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK
test Requests: OK
Total for mtk-cam-p1 device /dev/video27: 45, Succeeded: 45, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-cam-p1 device /dev/video28:
Driver Info:
Driver name : mtk-cam-p1
Card type : mtk-cam-p1
Bus info : platform:1a000000.camisp
Driver version : 4.19.59
Capabilities : 0x84a00000
Metadata Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04a00000
Metadata Capture
Streaming
Extended Pix Format
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Interface Info:
ID : 0x03000022
Type : V4L Video
Entity Info:
ID : 0x00000020 (32)
Name : mtk-cam-p1 partial meta 0
Function : V4L2 I/O
Pad 0x01000021 : 0: Sink
Link 0x02000024: from remote pad 0x1000005 of entity 'mtk-cam-p1': Data
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second /dev/video28 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK
test Requests: OK
Total for mtk-cam-p1 device /dev/video28: 45, Succeeded: 45, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-cam-p1 device /dev/video29:
Driver Info:
Driver name : mtk-cam-p1
Card type : mtk-cam-p1
Bus info : platform:1a000000.camisp
Driver version : 4.19.59
Capabilities : 0x84a00000
Metadata Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04a00000
Metadata Capture
Streaming
Extended Pix Format
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Interface Info:
ID : 0x03000028
Type : V4L Video
Entity Info:
ID : 0x00000026 (38)
Name : mtk-cam-p1 partial meta 1
Function : V4L2 I/O
Pad 0x01000027 : 0: Sink
Link 0x0200002a: from remote pad 0x1000006 of entity 'mtk-cam-p1': Data
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second /dev/video29 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK
test Requests: OK
Total for mtk-cam-p1 device /dev/video29: 45, Succeeded: 45, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-cam-p1 device /dev/video30:
Driver Info:
Driver name : mtk-cam-p1
Card type : mtk-cam-p1
Bus info : platform:1a000000.camisp
Driver version : 4.19.59
Capabilities : 0x84a00000
Metadata Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04a00000
Metadata Capture
Streaming
Extended Pix Format
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Interface Info:
ID : 0x0300002e
Type : V4L Video
Entity Info:
ID : 0x0000002c (44)
Name : mtk-cam-p1 partial meta 2
Function : V4L2 I/O
Pad 0x0100002d : 0: Sink
Link 0x02000030: from remote pad 0x1000007 of entity 'mtk-cam-p1': Data
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second /dev/video30 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK
test Requests: OK
Total for mtk-cam-p1 device /dev/video30: 45, Succeeded: 45, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-cam-p1 device /dev/video31:
Driver Info:
Driver name : mtk-cam-p1
Card type : mtk-cam-p1
Bus info : platform:1a000000.camisp
Driver version : 4.19.59
Capabilities : 0x84a00000
Metadata Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04a00000
Metadata Capture
Streaming
Extended Pix Format
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Interface Info:
ID : 0x03000034
Type : V4L Video
Entity Info:
ID : 0x00000032 (50)
Name : mtk-cam-p1 partial meta 3
Function : V4L2 I/O
Pad 0x01000033 : 0: Sink
Link 0x02000036: from remote pad 0x1000008 of entity 'mtk-cam-p1': Data
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second /dev/video31 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK
test Requests: OK
Total for mtk-cam-p1 device /dev/video31: 45, Succeeded: 45, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-cam-p1 device /dev/v4l-subdev5:
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Interface Info:
ID : 0x0300004f
Type : V4L Sub-Device
Entity Info:
ID : 0x00000001 (1)
Name : mtk-cam-p1
Function : Video Pixel Formatter
Pad 0x01000002 : 0: Sink
Link 0x02000012: from remote pad 0x100000f of entity 'mtk-cam-p1 meta input': Data
Pad 0x01000003 : 1: Source
Link 0x02000018: to remote pad 0x1000015 of entity 'mtk-cam-p1 main stream': Data, Enabled, Immutable
Pad 0x01000004 : 2: Source
Link 0x0200001e: to remote pad 0x100001b of entity 'mtk-cam-p1 packed out': Data
Pad 0x01000005 : 3: Source
Link 0x02000024: to remote pad 0x1000021 of entity 'mtk-cam-p1 partial meta 0': Data
Pad 0x01000006 : 4: Source
Link 0x0200002a: to remote pad 0x1000027 of entity 'mtk-cam-p1 partial meta 1': Data
Pad 0x01000007 : 5: Source
Link 0x02000030: to remote pad 0x100002d of entity 'mtk-cam-p1 partial meta 2': Data
Pad 0x01000008 : 6: Source
Link 0x02000036: to remote pad 0x1000033 of entity 'mtk-cam-p1 partial meta 3': Data
Pad 0x01000009 : 7: Source
Pad 0x0100000a : 8: Source
Pad 0x0100000b : 9: Source
Pad 0x0100000c : 10: Source
Pad 0x0100000d : 11: Sink
Link 0x0200004d: from remote pad 0x100003d of entity '1a040000.seninf.mipi-csi': Data, Enabled, Immutable
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
Allow for multiple opens:
test second /dev/v4l-subdev5 open: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Sub-Device ioctls (Sink Pad 0):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 1):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 2):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 3):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 4):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 5):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 6):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 7):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 8):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 9):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 10):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Sink Pad 11):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_FMT: OK (Not Supported)
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported)
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK (Not Supported)
test VIDIOC_TRY_FMT: OK (Not Supported)
test VIDIOC_S_FMT: OK (Not Supported)
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK (Not Supported)
test VIDIOC_EXPBUF: OK (Not Supported)
test Requests: OK (Not Supported)
Total for mtk-cam-p1 device /dev/v4l-subdev5: 125, Succeeded: 125, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-cam-p1 device /dev/v4l-subdev6:
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Interface Info:
ID : 0x03000051
Type : V4L Sub-Device
Entity Info:
ID : 0x00000038 (56)
Name : 1a040000.seninf.mipi-csi
Function : Video Interface Bridge
Pad 0x01000039 : 0: Sink
Link 0x02000047: from remote pad 0x1000046 of entity 'ov5695 2-0036': Data
Pad 0x0100003a : 1: Sink
Link 0x0200004b: from remote pad 0x100004a of entity 'ov2685 4-003c': Data
Pad 0x0100003b : 2: Sink
Pad 0x0100003c : 3: Sink
Pad 0x0100003d : 4: Source
Link 0x0200004d: to remote pad 0x100000d of entity 'mtk-cam-p1': Data, Enabled, Immutable
Pad 0x0100003e : 5: Source
Pad 0x0100003f : 6: Source
Pad 0x01000040 : 7: Source
Pad 0x01000041 : 8: Source
Pad 0x01000042 : 9: Source
Pad 0x01000043 : 10: Source
Pad 0x01000044 : 11: Source
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
Allow for multiple opens:
test second /dev/v4l-subdev6 open: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Sub-Device ioctls (Sink Pad 0):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Sink Pad 1):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(313): fmt.code == 0 || fmt.code == ~0U
fail: v4l2-test-subdevs.cpp(356): checkMBusFrameFmt(node, fmt.format)
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Sink Pad 2):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(313): fmt.code == 0 || fmt.code == ~0U
fail: v4l2-test-subdevs.cpp(356): checkMBusFrameFmt(node, fmt.format)
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Sink Pad 3):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(313): fmt.code == 0 || fmt.code == ~0U
fail: v4l2-test-subdevs.cpp(356): checkMBusFrameFmt(node, fmt.format)
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 4):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(313): fmt.code == 0 || fmt.code == ~0U
fail: v4l2-test-subdevs.cpp(356): checkMBusFrameFmt(node, fmt.format)
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 5):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(313): fmt.code == 0 || fmt.code == ~0U
fail: v4l2-test-subdevs.cpp(356): checkMBusFrameFmt(node, fmt.format)
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 6):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(313): fmt.code == 0 || fmt.code == ~0U
fail: v4l2-test-subdevs.cpp(356): checkMBusFrameFmt(node, fmt.format)
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 7):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(313): fmt.code == 0 || fmt.code == ~0U
fail: v4l2-test-subdevs.cpp(356): checkMBusFrameFmt(node, fmt.format)
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 8):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(313): fmt.code == 0 || fmt.code == ~0U
fail: v4l2-test-subdevs.cpp(356): checkMBusFrameFmt(node, fmt.format)
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 9):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(313): fmt.code == 0 || fmt.code == ~0U
fail: v4l2-test-subdevs.cpp(356): checkMBusFrameFmt(node, fmt.format)
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 10):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(313): fmt.code == 0 || fmt.code == ~0U
fail: v4l2-test-subdevs.cpp(356): checkMBusFrameFmt(node, fmt.format)
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 11):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(381): s_fmt.format.code == ~0U
test Try VIDIOC_SUBDEV_G/S_FMT: FAIL
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK (Not Supported)
fail: v4l2-test-subdevs.cpp(313): fmt.code == 0 || fmt.code == ~0U
fail: v4l2-test-subdevs.cpp(356): checkMBusFrameFmt(node, fmt.format)
test Active VIDIOC_SUBDEV_G/S_FMT: FAIL
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 2 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported)
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK (Not Supported)
test VIDIOC_TRY_FMT: OK (Not Supported)
test VIDIOC_S_FMT: OK (Not Supported)
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK (Not Supported)
test VIDIOC_EXPBUF: OK (Not Supported)
test Requests: OK (Not Supported)
Total for mtk-cam-p1 device /dev/v4l-subdev6: 125, Succeeded: 101, Failed: 24, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-cam-p1 device /dev/v4l-subdev7:
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Interface Info:
ID : 0x03000053
Type : V4L Sub-Device
Entity Info:
ID : 0x00000045 (69)
Name : ov5695 2-0036
Function : Camera Sensor
Pad 0x01000046 : 0: Source
Link 0x02000047: to remote pad 0x1000039 of entity '1a040000.seninf.mipi-csi': Data
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
Allow for multiple opens:
test second /dev/v4l-subdev7 open: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Sub-Device ioctls (Source Pad 0):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK
test Try VIDIOC_SUBDEV_G/S_FMT: OK
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK
test Active VIDIOC_SUBDEV_G/S_FMT: OK
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 11 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported)
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK (Not Supported)
test VIDIOC_TRY_FMT: OK (Not Supported)
test VIDIOC_S_FMT: OK (Not Supported)
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK (Not Supported)
test VIDIOC_EXPBUF: OK (Not Supported)
test Requests: OK (Not Supported)
Total for mtk-cam-p1 device /dev/v4l-subdev7: 48, Succeeded: 48, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-cam-p1 device /dev/v4l-subdev8:
Media Driver Info:
Driver name : mtk-cam-p1
Model : mtk-cam-p1
Serial :
Bus info : platform:1a000000.camisp
Media version : 4.19.59
Hardware revision: 0x00000000 (0)
Driver version : 4.19.59
Interface Info:
ID : 0x03000055
Type : V4L Sub-Device
Entity Info:
ID : 0x00000049 (73)
Name : ov2685 4-003c
Function : Camera Sensor
Pad 0x0100004a : 0: Source
Link 0x0200004b: to remote pad 0x100003a of entity '1a040000.seninf.mipi-csi': Data
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
Allow for multiple opens:
test second /dev/v4l-subdev8 open: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Sub-Device ioctls (Source Pad 0):
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK
test Try VIDIOC_SUBDEV_G/S_FMT: OK
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK
test Active VIDIOC_SUBDEV_G/S_FMT: OK
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK (Not Supported)
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 10 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported)
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK (Not Supported)
test VIDIOC_TRY_FMT: OK (Not Supported)
test VIDIOC_S_FMT: OK (Not Supported)
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK (Not Supported)
test VIDIOC_EXPBUF: OK (Not Supported)
test Requests: OK (Not Supported)
Total for mtk-cam-p1 device /dev/v4l-subdev8: 48, Succeeded: 48, Failed: 0, Warnings: 0
Grand Total for mtk-cam-p1 device /dev/media1: 668, Succeeded: 644, Failed: 24, Warnings: 0
=========================================================================================
Jungo Lin (4):
media: dt-bindings: mt8183: Added camera ISP Pass 1
dts: arm64: mt8183: Add ISP Pass 1 nodes
media: platform: Add Mediatek ISP P1 image & meta formats
media: platform: Add Mediatek ISP P1 V4L2 device driver
.../bindings/media/mediatek,camisp.txt | 73 +
.../media/uapi/v4l/pixfmt-mtisp-sbggr10.rst | 65 +
.../media/uapi/v4l/pixfmt-mtisp-sbggr10f.rst | 90 +
.../media/uapi/v4l/pixfmt-mtisp-sbggr12.rst | 61 +
.../media/uapi/v4l/pixfmt-mtisp-sbggr12f.rst | 110 +
.../media/uapi/v4l/pixfmt-mtisp-sbggr14.rst | 73 +
.../media/uapi/v4l/pixfmt-mtisp-sbggr14f.rst | 110 +
.../media/uapi/v4l/pixfmt-mtisp-sbggr8.rst | 51 +
.../media/uapi/v4l/pixfmt-mtisp-sbggr8f.rst | 78 +
Documentation/media/uapi/v4l/pixfmt-rgb.rst | 8 +
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 31 +
drivers/media/platform/Kconfig | 1 +
drivers/media/platform/Makefile | 1 +
drivers/media/platform/mtk-isp/Kconfig | 17 +
.../media/platform/mtk-isp/isp_50/Makefile | 3 +
.../platform/mtk-isp/isp_50/cam/Makefile | 6 +
.../platform/mtk-isp/isp_50/cam/mtk_cam-hw.c | 622 +++++
.../platform/mtk-isp/isp_50/cam/mtk_cam-hw.h | 65 +
.../platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h | 222 ++
.../mtk-isp/isp_50/cam/mtk_cam-regs.h | 95 +
.../platform/mtk-isp/isp_50/cam/mtk_cam.c | 2066 +++++++++++++++++
.../platform/mtk-isp/isp_50/cam/mtk_cam.h | 242 ++
drivers/media/v4l2-core/v4l2-ioctl.c | 37 +
include/uapi/linux/videodev2.h | 39 +
24 files changed, 4166 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/mediatek,camisp.txt
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr10.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr10f.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr12.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr12f.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr14.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr14f.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr8.rst
create mode 100644 Documentation/media/uapi/v4l/pixfmt-mtisp-sbggr8f.rst
create mode 100644 drivers/media/platform/mtk-isp/Kconfig
create mode 100644 drivers/media/platform/mtk-isp/isp_50/Makefile
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/Makefile
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.c
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.h
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-regs.h
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.c
create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.h
^ permalink raw reply
* Re: [PATCH 0/3] CP115 pinctrl support
From: Linus Walleij @ 2019-08-07 12:47 UTC (permalink / raw)
To: Miquel Raynal
Cc: Mark Rutland,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Yan Markman, Antoine Tenart, Grzegorz Jaszczyk, Gregory Clement,
Maxime Chevallier, Nadav Haklai, open list:GPIO SUBSYSTEM,
Rob Herring, Thomas Petazzoni, Stefan Chulski, Marcin Wojtas,
Linux ARM
In-Reply-To: <20190805101607.29811-1-miquel.raynal@bootlin.com>
On Mon, Aug 5, 2019 at 12:16 PM Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> This is the second batch of changes (out of three) to support the brand
> new Marvell CN9130 SoCs which are made of one AP807 and one CP115.
>
> We add a new compatible (and the relevant support in the pinctrl
> driver) before the addition in batch 3/3 of CN9130 SoCs DT using it.
Waiting for review from the Mvebu maintainers.
If it takes too long just nudge me, it looks good to me.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v3 2/2] pinctrl: qcom: Add SC7180 pinctrl driver
From: Linus Walleij @ 2019-08-07 12:44 UTC (permalink / raw)
To: Rajendra Nayak
Cc: Bjorn Andersson, MSM, Andy Gross, Rob Herring,
open list:GPIO SUBSYSTEM,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
linux-kernel@vger.kernel.org, Jitendra Sharma, Vivek Gautam,
Vinod Koul
In-Reply-To: <20190806060536.18094-2-rnayak@codeaurora.org>
On Tue, Aug 6, 2019 at 8:05 AM Rajendra Nayak <rnayak@codeaurora.org> wrote:
> From: Jitendra Sharma <shajit@codeaurora.org>
>
> Add initial pinctrl driver to support pin configuration with
> pinctrl framework for SC7180
>
> Signed-off-by: Jitendra Sharma <shajit@codeaurora.org>
> Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
> [rnayak: modify to use upstream tile support
> sort and squash some functions]
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> Reviewed-by: Vinod Koul <vkoul@kernel.org>
Patch applied!
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v3 1/2] dt-bindings: pinctrl: qcom: Add SC7180 pinctrl binding
From: Linus Walleij @ 2019-08-07 12:43 UTC (permalink / raw)
To: Rajendra Nayak
Cc: Bjorn Andersson, MSM, Andy Gross, Rob Herring,
open list:GPIO SUBSYSTEM,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
linux-kernel@vger.kernel.org, Jitendra Sharma, Vivek Gautam,
Vinod Koul
In-Reply-To: <20190806060536.18094-1-rnayak@codeaurora.org>
On Tue, Aug 6, 2019 at 8:05 AM Rajendra Nayak <rnayak@codeaurora.org> wrote:
> From: Jitendra Sharma <shajit@codeaurora.org>
>
> Add the binding for the TLMM pinctrl block found in the SC7180 platform
>
> Signed-off-by: Jitendra Sharma <shajit@codeaurora.org>
> Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
> [rnayak: Fix some copy-paste issues, sort and fix functions]
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> Reviewed-by: Vinod Koul <vkoul@kernel.org>
Patch applied.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v3] gpio: mpc8xxx: Add new platforms GPIO DT node description
From: Linus Walleij @ 2019-08-07 12:38 UTC (permalink / raw)
To: Hui Song
Cc: Shawn Guo, Li Yang, Rob Herring, Mark Rutland,
Bartosz Golaszewski, Linux ARM,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
linux-kernel@vger.kernel.org, open list:GPIO SUBSYSTEM
In-Reply-To: <20190807021254.49092-1-hui.song_1@nxp.com>
On Wed, Aug 7, 2019 at 4:22 AM Hui Song <hui.song_1@nxp.com> wrote:
> From: Song Hui <hui.song_1@nxp.com>
>
> Update the NXP GPIO node dt-binding file for QorIQ and
> Layerscape platforms, and add one more example with
> ls1028a GPIO node.
>
> Signed-off-by: Song Hui <hui.song_1@nxp.com>
Patch applied!
Thanks,
Linus Walleij
^ permalink raw reply
* [PATCHv1] arm64: dts: imx8qm: add compatible string for usdhc3
From: Oliver Graute @ 2019-08-07 12:09 UTC (permalink / raw)
To: aisheng.dong
Cc: oliver.graute, Rob Herring, Mark Rutland, Shawn Guo, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
Daniel Baluta, Ulf Hansson, devicetree, linux-arm-kernel,
linux-kernel
add compatible string for usdhc3
---
This Patch is on top of 10/15 of this series:
https://patchwork.kernel.org/patch/11046343/
[v2,10/15] arm64: dts: imx8qm: add conn ss support
---
arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi
index 00ae820d5175..8c33edf0744f 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi
@@ -19,3 +19,7 @@
&usdhc2 {
compatible = "fsl,imx8qm-usdhc", "fsl,imx7d-usdhc";
};
+
+&usdhc3 {
+ compatible = "fsl,imx8qm-usdhc", "fsl,imx7d-usdhc";
+};
--
2.17.1
^ permalink raw reply related
* Re: [PATCH v2 1/2] dt-bindings: net: snps,dwmac: update reg minItems maxItems
From: Maxime Ripard @ 2019-08-07 12:04 UTC (permalink / raw)
To: Rob Herring
Cc: Neil Armstrong, Martin Blumenstingl, devicetree, netdev,
linux-amlogic,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
linux-kernel@vger.kernel.org
In-Reply-To: <CAL_Jsq+6kCO8x53d1670VjgEjfs5opKY+R3OgsAo0WsXqq512Q@mail.gmail.com>
Hi,
On Tue, Aug 06, 2019 at 09:22:12AM -0600, Rob Herring wrote:
> +Maxime
>
> On Tue, Aug 6, 2019 at 6:50 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
> >
> > The Amlogic Meson DWMAC glue bindings needs a second reg cells for the
> > glue registers, thus update the reg minItems/maxItems to allow more
> > than a single reg cell.
> >
> > Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> > ---
> > Documentation/devicetree/bindings/net/snps,dwmac.yaml | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
>
> I haven't checked, but the derivative schema could be assuming this
> schema enforced reg is 1 item.
Yeah, we do for
Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml
(but somehow not allwinner,sun8i-a83t-emac.yaml)
Neil, can you add it to sun7i-a20-gmac?
> I don't think that's a major issue
> though.
>
> Acked-by: Rob Herring <robh@kernel.org>
With that fixed,
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
Maxime
--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox