Renesas R-Car DU fixes and improvements

-----BEGIN PGP SIGNATURE-----
 
 iJgEABYKAEAWIQTAnvhxs4J7QT+XHKnMPy2AAyfeZAUCY9QAUiIcbGF1cmVudC5w
 aW5jaGFydEBpZGVhc29uYm9hcmQuY29tAAoJEMw/LYADJ95kIlUA/ijw+E7QMW7w
 CbBfyFN+juM44qzpXhU14mdqcMmUmhYvAP9DyX3yxcwdwu3UMIiHHy04cH7Elwv5
 IO+EaGLUOxfIDg==
 =3wyo
 -----END PGP SIGNATURE-----

Merge tag 'drm-next-20230127' of git://git.kernel.org/pub/scm/linux/kernel/git/pinchartl/linux into drm-next

Renesas R-Car DU fixes and improvements

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/Y9QCw3SkHm6k1bwJ@pendragon.ideasonboard.com
This commit is contained in:
Dave Airlie 2023-01-30 13:49:46 +10:00
commit 54587d9943
25 changed files with 1034 additions and 185 deletions

View File

@ -11,13 +11,14 @@ maintainers:
description: |
This binding describes the MIPI DSI/CSI-2 encoder embedded in the Renesas
R-Car V3U SoC. The encoder can operate in either DSI or CSI-2 mode, with up
R-Car Gen4 SoCs. The encoder can operate in either DSI or CSI-2 mode, with up
to four data lanes.
properties:
compatible:
enum:
- renesas,r8a779a0-dsi-csi2-tx # for V3U
- renesas,r8a779g0-dsi-csi2-tx # for V4H
reg:
maxItems: 1

View File

@ -40,6 +40,7 @@ properties:
- renesas,du-r8a77990 # for R-Car E3 compatible DU
- renesas,du-r8a77995 # for R-Car D3 compatible DU
- renesas,du-r8a779a0 # for R-Car V3U compatible DU
- renesas,du-r8a779g0 # for R-Car V4H compatible DU
reg:
maxItems: 1
@ -762,6 +763,7 @@ allOf:
contains:
enum:
- renesas,du-r8a779a0
- renesas,du-r8a779g0
then:
properties:
clocks:

View File

@ -262,7 +262,12 @@ the second byte and Y'\ :sub:`7-0` in the third byte.
=================
These formats, commonly referred to as YUYV or YUY2, subsample the chroma
components horizontally by 2, storing 2 pixels in 4 bytes.
components horizontally by 2, storing 2 pixels in a container. The container
is 32-bits for 8-bit formats, and 64-bits for 10+-bit formats.
The packed YUYV formats with more than 8 bits per component are stored as four
16-bit little-endian words. Each word's most significant bits contain one
component, and the least significant bits are zero padding.
.. raw:: latex
@ -270,7 +275,7 @@ components horizontally by 2, storing 2 pixels in 4 bytes.
.. tabularcolumns:: |p{3.4cm}|p{1.2cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|
.. flat-table:: Packed YUV 4:2:2 Formats
.. flat-table:: Packed YUV 4:2:2 Formats in 32-bit container
:header-rows: 1
:stub-columns: 0
@ -337,6 +342,46 @@ components horizontally by 2, storing 2 pixels in 4 bytes.
- Y'\ :sub:`3`
- Cb\ :sub:`2`
.. tabularcolumns:: |p{3.4cm}|p{1.2cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|p{0.8cm}|
.. flat-table:: Packed YUV 4:2:2 Formats in 64-bit container
:header-rows: 1
:stub-columns: 0
* - Identifier
- Code
- Word 0
- Word 1
- Word 2
- Word 3
* .. _V4L2-PIX-FMT-Y210:
- ``V4L2_PIX_FMT_Y210``
- 'Y210'
- Y'\ :sub:`0` (bits 15-6)
- Cb\ :sub:`0` (bits 15-6)
- Y'\ :sub:`1` (bits 15-6)
- Cr\ :sub:`0` (bits 15-6)
* .. _V4L2-PIX-FMT-Y212:
- ``V4L2_PIX_FMT_Y212``
- 'Y212'
- Y'\ :sub:`0` (bits 15-4)
- Cb\ :sub:`0` (bits 15-4)
- Y'\ :sub:`1` (bits 15-4)
- Cr\ :sub:`0` (bits 15-4)
* .. _V4L2-PIX-FMT-Y216:
- ``V4L2_PIX_FMT_Y216``
- 'Y216'
- Y'\ :sub:`0` (bits 15-0)
- Cb\ :sub:`0` (bits 15-0)
- Y'\ :sub:`1` (bits 15-0)
- Cr\ :sub:`0` (bits 15-0)
.. raw:: latex
\normalsize

View File

@ -763,6 +763,200 @@ nomenclature that instead use the order of components as seen in a 24- or
\normalsize
10 Bits Per Component
=====================
These formats store a 30-bit RGB triplet with an optional 2 bit alpha in four
bytes. They are named based on the order of the RGB components as seen in a
32-bit word, which is then stored in memory in little endian byte order
(unless otherwise noted by the presence of bit 31 in the 4CC value), and on the
number of bits for each component.
.. raw:: latex
\begingroup
\tiny
\setlength{\tabcolsep}{2pt}
.. tabularcolumns:: |p{2.8cm}|p{2.0cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
.. flat-table:: RGB Formats 10 Bits Per Color Component
:header-rows: 2
:stub-columns: 0
* - Identifier
- Code
- :cspan:`7` Byte 0 in memory
- :cspan:`7` Byte 1
- :cspan:`7` Byte 2
- :cspan:`7` Byte 3
* -
-
- 7
- 6
- 5
- 4
- 3
- 2
- 1
- 0
- 7
- 6
- 5
- 4
- 3
- 2
- 1
- 0
- 7
- 6
- 5
- 4
- 3
- 2
- 1
- 0
- 7
- 6
- 5
- 4
- 3
- 2
- 1
- 0
* .. _V4L2-PIX-FMT-RGBX1010102:
- ``V4L2_PIX_FMT_RGBX1010102``
- 'RX30'
- b\ :sub:`5`
- b\ :sub:`4`
- b\ :sub:`3`
- b\ :sub:`2`
- b\ :sub:`1`
- b\ :sub:`0`
- x
- x
- g\ :sub:`3`
- g\ :sub:`2`
- g\ :sub:`1`
- g\ :sub:`0`
- b\ :sub:`9`
- b\ :sub:`8`
- b\ :sub:`7`
- b\ :sub:`6`
- r\ :sub:`1`
- r\ :sub:`0`
- g\ :sub:`9`
- g\ :sub:`8`
- g\ :sub:`7`
- g\ :sub:`6`
- g\ :sub:`5`
- g\ :sub:`4`
- r\ :sub:`9`
- r\ :sub:`8`
- r\ :sub:`7`
- r\ :sub:`6`
- r\ :sub:`5`
- r\ :sub:`4`
- r\ :sub:`3`
- r\ :sub:`2`
-
* .. _V4L2-PIX-FMT-RGBA1010102:
- ``V4L2_PIX_FMT_RGBA1010102``
- 'RA30'
- b\ :sub:`5`
- b\ :sub:`4`
- b\ :sub:`3`
- b\ :sub:`2`
- b\ :sub:`1`
- b\ :sub:`0`
- a\ :sub:`1`
- a\ :sub:`0`
- g\ :sub:`3`
- g\ :sub:`2`
- g\ :sub:`1`
- g\ :sub:`0`
- b\ :sub:`9`
- b\ :sub:`8`
- b\ :sub:`7`
- b\ :sub:`6`
- r\ :sub:`1`
- r\ :sub:`0`
- g\ :sub:`9`
- g\ :sub:`8`
- g\ :sub:`7`
- g\ :sub:`6`
- g\ :sub:`5`
- g\ :sub:`4`
- r\ :sub:`9`
- r\ :sub:`8`
- r\ :sub:`7`
- r\ :sub:`6`
- r\ :sub:`5`
- r\ :sub:`4`
- r\ :sub:`3`
- r\ :sub:`2`
-
* .. _V4L2-PIX-FMT-ARGB2101010:
- ``V4L2_PIX_FMT_ARGB2101010``
- 'AR30'
- b\ :sub:`7`
- b\ :sub:`6`
- b\ :sub:`5`
- b\ :sub:`4`
- b\ :sub:`3`
- b\ :sub:`2`
- b\ :sub:`1`
- b\ :sub:`0`
- g\ :sub:`5`
- g\ :sub:`4`
- g\ :sub:`3`
- g\ :sub:`2`
- g\ :sub:`1`
- g\ :sub:`0`
- b\ :sub:`9`
- b\ :sub:`8`
- r\ :sub:`3`
- r\ :sub:`2`
- r\ :sub:`1`
- r\ :sub:`0`
- g\ :sub:`9`
- g\ :sub:`8`
- g\ :sub:`7`
- g\ :sub:`6`
- a\ :sub:`1`
- a\ :sub:`0`
- r\ :sub:`9`
- r\ :sub:`8`
- r\ :sub:`7`
- r\ :sub:`6`
- r\ :sub:`5`
- r\ :sub:`4`
-
.. raw:: latex
\endgroup
Deprecated RGB Formats
======================

View File

@ -25,6 +25,7 @@ config DRM_RCAR_CMM
config DRM_RCAR_DW_HDMI
tristate "R-Car Gen3 and RZ/G2 DU HDMI Encoder Support"
depends on DRM && OF
depends on DRM_RCAR_DU || COMPILE_TEST
select DRM_DW_HDMI
help
Enable support for R-Car Gen3 or RZ/G2 internal HDMI encoder.
@ -32,6 +33,7 @@ config DRM_RCAR_DW_HDMI
config DRM_RCAR_USE_LVDS
bool "R-Car DU LVDS Encoder Support"
depends on DRM_BRIDGE && OF
depends on DRM_RCAR_DU || COMPILE_TEST
default DRM_RCAR_DU
help
Enable support for the R-Car Display Unit embedded LVDS encoders.
@ -39,12 +41,15 @@ config DRM_RCAR_USE_LVDS
config DRM_RCAR_LVDS
def_tristate DRM_RCAR_DU
depends on DRM_RCAR_USE_LVDS
depends on PM
select DRM_KMS_HELPER
select DRM_PANEL
select RESET_CONTROLLER
config DRM_RCAR_USE_MIPI_DSI
bool "R-Car DU MIPI DSI Encoder Support"
depends on DRM_BRIDGE && OF
depends on DRM_RCAR_DU || COMPILE_TEST
default DRM_RCAR_DU
help
Enable support for the R-Car Display Unit embedded MIPI DSI encoders.
@ -53,6 +58,7 @@ config DRM_RCAR_MIPI_DSI
def_tristate DRM_RCAR_DU
depends on DRM_RCAR_USE_MIPI_DSI
select DRM_MIPI_DSI
select RESET_CONTROLLER
config DRM_RZG2L_MIPI_DSI
tristate "RZ/G2L MIPI DSI Encoder Support"

View File

@ -10,7 +10,6 @@
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/sys_soc.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
@ -204,11 +203,6 @@ static void rcar_du_escr_divider(struct clk *clk, unsigned long target,
}
}
static const struct soc_device_attribute rcar_du_r8a7795_es1[] = {
{ .soc_id = "r8a7795", .revision = "ES1.*" },
{ /* sentinel */ }
};
static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
{
const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
@ -238,7 +232,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
* no post-divider when a display PLL is present (as shown by
* the workaround breaking HDMI output on M3-W during testing).
*/
if (soc_device_match(rcar_du_r8a7795_es1)) {
if (rcdu->info->quirks & RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY) {
target *= 2;
div = 1;
}
@ -251,13 +245,30 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
| DPLLCR_N(dpll.n) | DPLLCR_M(dpll.m)
| DPLLCR_STBY;
if (rcrtc->index == 1)
if (rcrtc->index == 1) {
dpllcr |= DPLLCR_PLCS1
| DPLLCR_INCS_DOTCLKIN1;
else
dpllcr |= DPLLCR_PLCS0
} else {
dpllcr |= DPLLCR_PLCS0_PLL
| DPLLCR_INCS_DOTCLKIN0;
/*
* On ES2.x we have a single mux controlled via bit 21,
* which selects between DCLKIN source (bit 21 = 0) and
* a PLL source (bit 21 = 1), where the PLL is always
* PLL1.
*
* On ES1.x we have an additional mux, controlled
* via bit 20, for choosing between PLL0 (bit 20 = 0)
* and PLL1 (bit 20 = 1). We always want to use PLL1,
* so on ES1.x, in addition to setting bit 21, we need
* to set the bit 20.
*/
if (rcdu->info->quirks & RCAR_DU_QUIRK_H3_ES1_PLL)
dpllcr |= DPLLCR_PLCS0_H3ES1X_PLL1;
}
rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
escr = ESCR_DCLKSEL_DCLKIN | div;
@ -287,10 +298,12 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
escr = params.escr;
}
dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr);
if (rcdu->info->gen < 4) {
dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr);
rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr);
rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0);
rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr);
rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0);
}
/* Signal polarities */
dsmr = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)

View File

@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include <linux/wait.h>
#include <drm/drm_atomic_helper.h>
@ -386,6 +387,43 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
.dpll_mask = BIT(2) | BIT(1),
};
static const struct rcar_du_device_info rcar_du_r8a7795_es1_info = {
.gen = 3,
.features = RCAR_DU_FEATURE_CRTC_IRQ
| RCAR_DU_FEATURE_CRTC_CLOCK
| RCAR_DU_FEATURE_VSP1_SOURCE
| RCAR_DU_FEATURE_INTERLACED
| RCAR_DU_FEATURE_TVM_SYNC,
.quirks = RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY
| RCAR_DU_QUIRK_H3_ES1_PLL,
.channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
.routes = {
/*
* R8A7795 has one RGB output, two HDMI outputs and one
* LVDS output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(3),
.port = 0,
},
[RCAR_DU_OUTPUT_HDMI0] = {
.possible_crtcs = BIT(1),
.port = 1,
},
[RCAR_DU_OUTPUT_HDMI1] = {
.possible_crtcs = BIT(2),
.port = 2,
},
[RCAR_DU_OUTPUT_LVDS0] = {
.possible_crtcs = BIT(0),
.port = 3,
},
},
.num_lvds = 1,
.num_rpf = 5,
.dpll_mask = BIT(2) | BIT(1),
};
static const struct rcar_du_device_info rcar_du_r8a7796_info = {
.gen = 3,
.features = RCAR_DU_FEATURE_CRTC_IRQ
@ -504,7 +542,7 @@ static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
};
static const struct rcar_du_device_info rcar_du_r8a779a0_info = {
.gen = 3,
.gen = 4,
.features = RCAR_DU_FEATURE_CRTC_IRQ
| RCAR_DU_FEATURE_VSP1_SOURCE
| RCAR_DU_FEATURE_NO_BLENDING,
@ -524,6 +562,27 @@ static const struct rcar_du_device_info rcar_du_r8a779a0_info = {
.dsi_clk_mask = BIT(1) | BIT(0),
};
static const struct rcar_du_device_info rcar_du_r8a779g0_info = {
.gen = 4,
.features = RCAR_DU_FEATURE_CRTC_IRQ
| RCAR_DU_FEATURE_VSP1_SOURCE
| RCAR_DU_FEATURE_NO_BLENDING,
.channels_mask = BIT(1) | BIT(0),
.routes = {
/* R8A779G0 has two MIPI DSI outputs. */
[RCAR_DU_OUTPUT_DSI0] = {
.possible_crtcs = BIT(0),
.port = 0,
},
[RCAR_DU_OUTPUT_DSI1] = {
.possible_crtcs = BIT(1),
.port = 1,
},
},
.num_rpf = 5,
.dsi_clk_mask = BIT(1) | BIT(0),
};
static const struct of_device_id rcar_du_of_table[] = {
{ .compatible = "renesas,du-r8a7742", .data = &rcar_du_r8a7790_info },
{ .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info },
@ -549,11 +608,17 @@ static const struct of_device_id rcar_du_of_table[] = {
{ .compatible = "renesas,du-r8a77990", .data = &rcar_du_r8a7799x_info },
{ .compatible = "renesas,du-r8a77995", .data = &rcar_du_r8a7799x_info },
{ .compatible = "renesas,du-r8a779a0", .data = &rcar_du_r8a779a0_info },
{ .compatible = "renesas,du-r8a779g0", .data = &rcar_du_r8a779g0_info },
{ }
};
MODULE_DEVICE_TABLE(of, rcar_du_of_table);
static const struct soc_device_attribute rcar_du_soc_table[] = {
{ .soc_id = "r8a7795", .revision = "ES1.*", .data = &rcar_du_r8a7795_es1_info },
{ /* sentinel */ }
};
const char *rcar_du_output_name(enum rcar_du_output output)
{
static const char * const names[] = {
@ -642,6 +707,7 @@ static void rcar_du_shutdown(struct platform_device *pdev)
static int rcar_du_probe(struct platform_device *pdev)
{
const struct soc_device_attribute *soc_attr;
struct rcar_du_device *rcdu;
unsigned int mask;
int ret;
@ -656,8 +722,13 @@ static int rcar_du_probe(struct platform_device *pdev)
return PTR_ERR(rcdu);
rcdu->dev = &pdev->dev;
rcdu->info = of_device_get_match_data(rcdu->dev);
soc_attr = soc_device_match(rcar_du_soc_table);
if (soc_attr)
rcdu->info = soc_attr->data;
platform_set_drvdata(pdev, rcdu);
/* I/O resources */

View File

@ -34,6 +34,8 @@ struct rcar_du_device;
#define RCAR_DU_FEATURE_NO_BLENDING BIT(5) /* PnMR.SPIM does not have ALP nor EOR bits */
#define RCAR_DU_QUIRK_ALIGN_128B BIT(0) /* Align pitches to 128 bytes */
#define RCAR_DU_QUIRK_H3_ES1_PCLK_STABILITY BIT(1) /* H3 ES1 has pclk stability issue */
#define RCAR_DU_QUIRK_H3_ES1_PLL BIT(2) /* H3 ES1 PLL setup differs from non-ES1 */
enum rcar_du_output {
RCAR_DU_OUTPUT_DPAD0,

View File

@ -107,7 +107,7 @@ static void rcar_du_group_setup_didsr(struct rcar_du_group *rgrp)
*/
rcrtc = rcdu->crtcs;
num_crtcs = rcdu->num_crtcs;
} else if (rcdu->info->gen == 3 && rgrp->num_crtcs > 1) {
} else if (rcdu->info->gen >= 3 && rgrp->num_crtcs > 1) {
/*
* On Gen3 dot clocks are setup through per-group registers,
* only available when the group has two channels.
@ -148,19 +148,23 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
}
rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
rcar_du_group_setup_pins(rgrp);
if (rcdu->info->gen < 4)
rcar_du_group_setup_pins(rgrp);
/*
* TODO: Handle routing of the DU output to CMM dynamically, as we
* should bypass CMM completely when no color management feature is
* used.
*/
defr7 |= (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0) |
(rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
rcar_du_group_write(rgrp, DEFR7, defr7);
if (rcdu->info->gen < 4) {
/*
* TODO: Handle routing of the DU output to CMM dynamically, as
* we should bypass CMM completely when no color management
* feature is used.
*/
defr7 |= (rgrp->cmms_mask & BIT(1) ? DEFR7_CMME1 : 0) |
(rgrp->cmms_mask & BIT(0) ? DEFR7_CMME0 : 0);
rcar_du_group_write(rgrp, DEFR7, defr7);
}
if (rcdu->info->gen >= 2) {
rcar_du_group_setup_defr8(rgrp);
if (rcdu->info->gen < 4)
rcar_du_group_setup_defr8(rgrp);
rcar_du_group_setup_didsr(rgrp);
}

View File

@ -259,6 +259,24 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = {
.bpp = 32,
.planes = 1,
.hsub = 1,
}, {
.fourcc = DRM_FORMAT_RGBX1010102,
.v4l2 = V4L2_PIX_FMT_RGBX1010102,
.bpp = 32,
.planes = 1,
.hsub = 1,
}, {
.fourcc = DRM_FORMAT_RGBA1010102,
.v4l2 = V4L2_PIX_FMT_RGBA1010102,
.bpp = 32,
.planes = 1,
.hsub = 1,
}, {
.fourcc = DRM_FORMAT_ARGB2101010,
.v4l2 = V4L2_PIX_FMT_ARGB2101010,
.bpp = 32,
.planes = 1,
.hsub = 1,
}, {
.fourcc = DRM_FORMAT_YVYU,
.v4l2 = V4L2_PIX_FMT_YVYU,
@ -307,6 +325,18 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = {
.bpp = 24,
.planes = 3,
.hsub = 1,
}, {
.fourcc = DRM_FORMAT_Y210,
.v4l2 = V4L2_PIX_FMT_Y210,
.bpp = 32,
.planes = 1,
.hsub = 2,
}, {
.fourcc = DRM_FORMAT_Y212,
.v4l2 = V4L2_PIX_FMT_Y212,
.bpp = 32,
.planes = 1,
.hsub = 2,
},
};

View File

@ -283,12 +283,8 @@
#define DPLLCR 0x20044
#define DPLLCR_CODE (0x95 << 24)
#define DPLLCR_PLCS1 (1 << 23)
/*
* PLCS0 is bit 21, but H3 ES1.x requires bit 20 to be set as well. As bit 20
* isn't implemented by other SoC in the Gen3 family it can safely be set
* unconditionally.
*/
#define DPLLCR_PLCS0 (3 << 20)
#define DPLLCR_PLCS0_PLL (1 << 21)
#define DPLLCR_PLCS0_H3ES1X_PLL1 (1 << 20)
#define DPLLCR_CLKE (1 << 18)
#define DPLLCR_FDPLL(n) ((n) << 12)
#define DPLLCR_N(n) ((n) << 5)

View File

@ -139,6 +139,43 @@ static const u32 rcar_du_vsp_formats[] = {
DRM_FORMAT_YVU444,
};
/*
* Gen4 supports the same formats as above, and additionally 2-10-10-10 RGB
* formats and Y210 & Y212 formats.
*/
static const u32 rcar_du_vsp_formats_gen4[] = {
DRM_FORMAT_RGB332,
DRM_FORMAT_ARGB4444,
DRM_FORMAT_XRGB4444,
DRM_FORMAT_ARGB1555,
DRM_FORMAT_XRGB1555,
DRM_FORMAT_RGB565,
DRM_FORMAT_BGR888,
DRM_FORMAT_RGB888,
DRM_FORMAT_BGRA8888,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_ARGB8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_RGBX1010102,
DRM_FORMAT_RGBA1010102,
DRM_FORMAT_ARGB2101010,
DRM_FORMAT_UYVY,
DRM_FORMAT_YUYV,
DRM_FORMAT_YVYU,
DRM_FORMAT_NV12,
DRM_FORMAT_NV21,
DRM_FORMAT_NV16,
DRM_FORMAT_NV61,
DRM_FORMAT_YUV420,
DRM_FORMAT_YVU420,
DRM_FORMAT_YUV422,
DRM_FORMAT_YVU422,
DRM_FORMAT_YUV444,
DRM_FORMAT_YVU444,
DRM_FORMAT_Y210,
DRM_FORMAT_Y212,
};
static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
{
struct rcar_du_vsp_plane_state *state =
@ -436,14 +473,23 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np,
? DRM_PLANE_TYPE_PRIMARY
: DRM_PLANE_TYPE_OVERLAY;
struct rcar_du_vsp_plane *plane = &vsp->planes[i];
unsigned int num_formats;
const u32 *formats;
if (rcdu->info->gen < 4) {
num_formats = ARRAY_SIZE(rcar_du_vsp_formats);
formats = rcar_du_vsp_formats;
} else {
num_formats = ARRAY_SIZE(rcar_du_vsp_formats_gen4);
formats = rcar_du_vsp_formats_gen4;
}
plane->vsp = vsp;
plane->index = i;
ret = drm_universal_plane_init(&rcdu->ddev, &plane->plane,
crtcs, &rcar_du_vsp_plane_funcs,
rcar_du_vsp_formats,
ARRAY_SIZE(rcar_du_vsp_formats),
formats, num_formats,
NULL, type, NULL);
if (ret < 0)
return ret;

View File

@ -16,6 +16,8 @@
#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
@ -60,6 +62,7 @@ struct rcar_lvds_device_info {
struct rcar_lvds {
struct device *dev;
const struct rcar_lvds_device_info *info;
struct reset_control *rstc;
struct drm_bridge bridge;
@ -80,6 +83,11 @@ struct rcar_lvds {
#define bridge_to_rcar_lvds(b) \
container_of(b, struct rcar_lvds, bridge)
static u32 rcar_lvds_read(struct rcar_lvds *lvds, u32 reg)
{
return ioread32(lvds->mmio + reg);
}
static void rcar_lvds_write(struct rcar_lvds *lvds, u32 reg, u32 data)
{
iowrite32(data, lvds->mmio + reg);
@ -316,8 +324,8 @@ int rcar_lvds_pclk_enable(struct drm_bridge *bridge, unsigned long freq)
dev_dbg(lvds->dev, "enabling LVDS PLL, freq=%luHz\n", freq);
ret = clk_prepare_enable(lvds->clocks.mod);
if (ret < 0)
ret = pm_runtime_resume_and_get(lvds->dev);
if (ret)
return ret;
__rcar_lvds_pll_setup_d3_e3(lvds, freq, true);
@ -337,7 +345,7 @@ void rcar_lvds_pclk_disable(struct drm_bridge *bridge)
rcar_lvds_write(lvds, LVDPLLCR, 0);
clk_disable_unprepare(lvds->clocks.mod);
pm_runtime_put_sync(lvds->dev);
}
EXPORT_SYMBOL_GPL(rcar_lvds_pclk_disable);
@ -396,8 +404,8 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge,
u32 lvdcr0;
int ret;
ret = clk_prepare_enable(lvds->clocks.mod);
if (ret < 0)
ret = pm_runtime_resume_and_get(lvds->dev);
if (ret)
return;
/* Enable the companion LVDS encoder in dual-link mode. */
@ -541,6 +549,32 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
u32 lvdcr0;
/*
* Clear the LVDCR0 bits in the order specified by the hardware
* documentation, ending with a write of 0 to the full register to
* clear all remaining bits.
*/
lvdcr0 = rcar_lvds_read(lvds, LVDCR0);
lvdcr0 &= ~LVDCR0_LVRES;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN3_LVEN) {
lvdcr0 &= ~LVDCR0_LVEN;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
}
if (lvds->info->quirks & RCAR_LVDS_QUIRK_PWD) {
lvdcr0 &= ~LVDCR0_PWD;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
}
if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
lvdcr0 &= ~LVDCR0_PLLON;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
}
rcar_lvds_write(lvds, LVDCR0, 0);
rcar_lvds_write(lvds, LVDCR1, 0);
@ -551,7 +585,7 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
lvds->companion->funcs->atomic_disable(lvds->companion,
old_bridge_state);
clk_disable_unprepare(lvds->clocks.mod);
pm_runtime_put_sync(lvds->dev);
}
static bool rcar_lvds_mode_fixup(struct drm_bridge *bridge,
@ -844,6 +878,13 @@ static int rcar_lvds_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
lvds->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(lvds->rstc))
return dev_err_probe(&pdev->dev, PTR_ERR(lvds->rstc),
"failed to get cpg reset\n");
pm_runtime_enable(&pdev->dev);
drm_bridge_add(&lvds->bridge);
return 0;
@ -855,6 +896,8 @@ static int rcar_lvds_remove(struct platform_device *pdev)
drm_bridge_remove(&lvds->bridge);
pm_runtime_disable(&pdev->dev);
return 0;
}
@ -913,11 +956,48 @@ static const struct of_device_id rcar_lvds_of_table[] = {
MODULE_DEVICE_TABLE(of, rcar_lvds_of_table);
static int rcar_lvds_runtime_suspend(struct device *dev)
{
struct rcar_lvds *lvds = dev_get_drvdata(dev);
clk_disable_unprepare(lvds->clocks.mod);
reset_control_assert(lvds->rstc);
return 0;
}
static int rcar_lvds_runtime_resume(struct device *dev)
{
struct rcar_lvds *lvds = dev_get_drvdata(dev);
int ret;
ret = reset_control_deassert(lvds->rstc);
if (ret)
return ret;
ret = clk_prepare_enable(lvds->clocks.mod);
if (ret < 0)
goto err_reset_assert;
return 0;
err_reset_assert:
reset_control_assert(lvds->rstc);
return ret;
}
static const struct dev_pm_ops rcar_lvds_pm_ops = {
SET_RUNTIME_PM_OPS(rcar_lvds_runtime_suspend, rcar_lvds_runtime_resume, NULL)
};
static struct platform_driver rcar_lvds_platform_driver = {
.probe = rcar_lvds_probe,
.remove = rcar_lvds_remove,
.driver = {
.name = "rcar-lvds",
.pm = &rcar_lvds_pm_ops,
.of_match_table = rcar_lvds_of_table,
},
};

View File

@ -9,6 +9,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/math64.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
@ -28,6 +29,31 @@
#include "rcar_mipi_dsi.h"
#include "rcar_mipi_dsi_regs.h"
#define MHZ(v) ((u32)((v) * 1000000U))
enum rcar_mipi_dsi_hw_model {
RCAR_DSI_V3U,
RCAR_DSI_V4H,
};
struct rcar_mipi_dsi_device_info {
enum rcar_mipi_dsi_hw_model model;
const struct dsi_clk_config *clk_cfg;
u8 clockset2_m_offset;
u8 n_min;
u8 n_max;
u8 n_mul;
unsigned long fpfd_min;
unsigned long fpfd_max;
u16 m_min;
u16 m_max;
unsigned long fout_min;
unsigned long fout_max;
};
struct rcar_mipi_dsi {
struct device *dev;
const struct rcar_mipi_dsi_device_info *info;
@ -50,6 +76,17 @@ struct rcar_mipi_dsi {
unsigned int lanes;
};
struct dsi_setup_info {
unsigned long hsfreq;
u16 hsfreqrange;
unsigned long fout;
u16 m;
u16 n;
u16 vclk_divider;
const struct dsi_clk_config *clkset;
};
static inline struct rcar_mipi_dsi *
bridge_to_rcar_mipi_dsi(struct drm_bridge *bridge)
{
@ -62,65 +99,78 @@ host_to_rcar_mipi_dsi(struct mipi_dsi_host *host)
return container_of(host, struct rcar_mipi_dsi, host);
}
static const u32 phtw[] = {
0x01020114, 0x01600115, /* General testing */
0x01030116, 0x0102011d, /* General testing */
0x011101a4, 0x018601a4, /* 1Gbps testing */
0x014201a0, 0x010001a3, /* 1Gbps testing */
0x0101011f, /* 1Gbps testing */
};
static const u32 phtw2[] = {
0x010c0130, 0x010c0140, /* General testing */
0x010c0150, 0x010c0180, /* General testing */
0x010c0190,
0x010a0160, 0x010a0170,
0x01800164, 0x01800174, /* 1Gbps testing */
};
static const u32 hsfreqrange_table[][2] = {
{ 80000000U, 0x00 }, { 90000000U, 0x10 }, { 100000000U, 0x20 },
{ 110000000U, 0x30 }, { 120000000U, 0x01 }, { 130000000U, 0x11 },
{ 140000000U, 0x21 }, { 150000000U, 0x31 }, { 160000000U, 0x02 },
{ 170000000U, 0x12 }, { 180000000U, 0x22 }, { 190000000U, 0x32 },
{ 205000000U, 0x03 }, { 220000000U, 0x13 }, { 235000000U, 0x23 },
{ 250000000U, 0x33 }, { 275000000U, 0x04 }, { 300000000U, 0x14 },
{ 325000000U, 0x25 }, { 350000000U, 0x35 }, { 400000000U, 0x05 },
{ 450000000U, 0x16 }, { 500000000U, 0x26 }, { 550000000U, 0x37 },
{ 600000000U, 0x07 }, { 650000000U, 0x18 }, { 700000000U, 0x28 },
{ 750000000U, 0x39 }, { 800000000U, 0x09 }, { 850000000U, 0x19 },
{ 900000000U, 0x29 }, { 950000000U, 0x3a }, { 1000000000U, 0x0a },
{ 1050000000U, 0x1a }, { 1100000000U, 0x2a }, { 1150000000U, 0x3b },
{ 1200000000U, 0x0b }, { 1250000000U, 0x1b }, { 1300000000U, 0x2b },
{ 1350000000U, 0x3c }, { 1400000000U, 0x0c }, { 1450000000U, 0x1c },
{ 1500000000U, 0x2c }, { 1550000000U, 0x3d }, { 1600000000U, 0x0d },
{ 1650000000U, 0x1d }, { 1700000000U, 0x2e }, { 1750000000U, 0x3e },
{ 1800000000U, 0x0e }, { 1850000000U, 0x1e }, { 1900000000U, 0x2f },
{ 1950000000U, 0x3f }, { 2000000000U, 0x0f }, { 2050000000U, 0x40 },
{ 2100000000U, 0x41 }, { 2150000000U, 0x42 }, { 2200000000U, 0x43 },
{ 2250000000U, 0x44 }, { 2300000000U, 0x45 }, { 2350000000U, 0x46 },
{ 2400000000U, 0x47 }, { 2450000000U, 0x48 }, { 2500000000U, 0x49 },
{ MHZ(80), 0x00 }, { MHZ(90), 0x10 }, { MHZ(100), 0x20 },
{ MHZ(110), 0x30 }, { MHZ(120), 0x01 }, { MHZ(130), 0x11 },
{ MHZ(140), 0x21 }, { MHZ(150), 0x31 }, { MHZ(160), 0x02 },
{ MHZ(170), 0x12 }, { MHZ(180), 0x22 }, { MHZ(190), 0x32 },
{ MHZ(205), 0x03 }, { MHZ(220), 0x13 }, { MHZ(235), 0x23 },
{ MHZ(250), 0x33 }, { MHZ(275), 0x04 }, { MHZ(300), 0x14 },
{ MHZ(325), 0x25 }, { MHZ(350), 0x35 }, { MHZ(400), 0x05 },
{ MHZ(450), 0x16 }, { MHZ(500), 0x26 }, { MHZ(550), 0x37 },
{ MHZ(600), 0x07 }, { MHZ(650), 0x18 }, { MHZ(700), 0x28 },
{ MHZ(750), 0x39 }, { MHZ(800), 0x09 }, { MHZ(850), 0x19 },
{ MHZ(900), 0x29 }, { MHZ(950), 0x3a }, { MHZ(1000), 0x0a },
{ MHZ(1050), 0x1a }, { MHZ(1100), 0x2a }, { MHZ(1150), 0x3b },
{ MHZ(1200), 0x0b }, { MHZ(1250), 0x1b }, { MHZ(1300), 0x2b },
{ MHZ(1350), 0x3c }, { MHZ(1400), 0x0c }, { MHZ(1450), 0x1c },
{ MHZ(1500), 0x2c }, { MHZ(1550), 0x3d }, { MHZ(1600), 0x0d },
{ MHZ(1650), 0x1d }, { MHZ(1700), 0x2e }, { MHZ(1750), 0x3e },
{ MHZ(1800), 0x0e }, { MHZ(1850), 0x1e }, { MHZ(1900), 0x2f },
{ MHZ(1950), 0x3f }, { MHZ(2000), 0x0f }, { MHZ(2050), 0x40 },
{ MHZ(2100), 0x41 }, { MHZ(2150), 0x42 }, { MHZ(2200), 0x43 },
{ MHZ(2250), 0x44 }, { MHZ(2300), 0x45 }, { MHZ(2350), 0x46 },
{ MHZ(2400), 0x47 }, { MHZ(2450), 0x48 }, { MHZ(2500), 0x49 },
{ /* sentinel */ },
};
struct vco_cntrl_value {
struct dsi_clk_config {
u32 min_freq;
u32 max_freq;
u16 value;
u8 vco_cntrl;
u8 cpbias_cntrl;
u8 gmp_cntrl;
u8 int_cntrl;
u8 prop_cntrl;
};
static const struct vco_cntrl_value vco_cntrl_table[] = {
{ .min_freq = 40000000U, .max_freq = 55000000U, .value = 0x3f },
{ .min_freq = 52500000U, .max_freq = 80000000U, .value = 0x39 },
{ .min_freq = 80000000U, .max_freq = 110000000U, .value = 0x2f },
{ .min_freq = 105000000U, .max_freq = 160000000U, .value = 0x29 },
{ .min_freq = 160000000U, .max_freq = 220000000U, .value = 0x1f },
{ .min_freq = 210000000U, .max_freq = 320000000U, .value = 0x19 },
{ .min_freq = 320000000U, .max_freq = 440000000U, .value = 0x0f },
{ .min_freq = 420000000U, .max_freq = 660000000U, .value = 0x09 },
{ .min_freq = 630000000U, .max_freq = 1149000000U, .value = 0x03 },
{ .min_freq = 1100000000U, .max_freq = 1152000000U, .value = 0x01 },
{ .min_freq = 1150000000U, .max_freq = 1250000000U, .value = 0x01 },
static const struct dsi_clk_config dsi_clk_cfg_v3u[] = {
{ MHZ(40), MHZ(55), 0x3f, 0x10, 0x01, 0x00, 0x0b },
{ MHZ(52.5), MHZ(80), 0x39, 0x10, 0x01, 0x00, 0x0b },
{ MHZ(80), MHZ(110), 0x2f, 0x10, 0x01, 0x00, 0x0b },
{ MHZ(105), MHZ(160), 0x29, 0x10, 0x01, 0x00, 0x0b },
{ MHZ(160), MHZ(220), 0x1f, 0x10, 0x01, 0x00, 0x0b },
{ MHZ(210), MHZ(320), 0x19, 0x10, 0x01, 0x00, 0x0b },
{ MHZ(320), MHZ(440), 0x0f, 0x10, 0x01, 0x00, 0x0b },
{ MHZ(420), MHZ(660), 0x09, 0x10, 0x01, 0x00, 0x0b },
{ MHZ(630), MHZ(1149), 0x03, 0x10, 0x01, 0x00, 0x0b },
{ MHZ(1100), MHZ(1152), 0x01, 0x10, 0x01, 0x00, 0x0b },
{ MHZ(1150), MHZ(1250), 0x01, 0x10, 0x01, 0x00, 0x0c },
{ /* sentinel */ },
};
static const struct dsi_clk_config dsi_clk_cfg_v4h[] = {
{ MHZ(40), MHZ(45.31), 0x2b, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(45.31), MHZ(54.66), 0x28, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(54.66), MHZ(62.5), 0x28, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(62.5), MHZ(75), 0x27, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(75), MHZ(90.63), 0x23, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(90.63), MHZ(109.37), 0x20, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(109.37), MHZ(125), 0x20, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(125), MHZ(150), 0x1f, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(150), MHZ(181.25), 0x1b, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(181.25), MHZ(218.75), 0x18, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(218.75), MHZ(250), 0x18, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(250), MHZ(300), 0x17, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(300), MHZ(362.5), 0x13, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(362.5), MHZ(455.48), 0x10, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(455.48), MHZ(500), 0x10, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(500), MHZ(600), 0x0f, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(600), MHZ(725), 0x0b, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(725), MHZ(875), 0x08, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(875), MHZ(1000), 0x08, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(1000), MHZ(1200), 0x07, 0x00, 0x00, 0x08, 0x0a },
{ MHZ(1200), MHZ(1250), 0x03, 0x00, 0x00, 0x08, 0x0a },
{ /* sentinel */ },
};
@ -144,7 +194,7 @@ static void rcar_mipi_dsi_set(struct rcar_mipi_dsi *dsi, u32 reg, u32 set)
rcar_mipi_dsi_write(dsi, reg, rcar_mipi_dsi_read(dsi, reg) | set);
}
static int rcar_mipi_dsi_phtw_test(struct rcar_mipi_dsi *dsi, u32 phtw)
static int rcar_mipi_dsi_write_phtw(struct rcar_mipi_dsi *dsi, u32 phtw)
{
u32 status;
int ret;
@ -163,32 +213,181 @@ static int rcar_mipi_dsi_phtw_test(struct rcar_mipi_dsi *dsi, u32 phtw)
return ret;
}
static int rcar_mipi_dsi_write_phtw_arr(struct rcar_mipi_dsi *dsi,
const u32 *phtw, unsigned int size)
{
for (unsigned int i = 0; i < size; i++) {
int ret = rcar_mipi_dsi_write_phtw(dsi, phtw[i]);
if (ret < 0)
return ret;
}
return 0;
}
#define WRITE_PHTW(...) \
({ \
static const u32 phtw[] = { __VA_ARGS__ }; \
int ret; \
ret = rcar_mipi_dsi_write_phtw_arr(dsi, phtw, \
ARRAY_SIZE(phtw)); \
ret; \
})
static int rcar_mipi_dsi_init_phtw_v3u(struct rcar_mipi_dsi *dsi)
{
return WRITE_PHTW(0x01020114, 0x01600115, 0x01030116, 0x0102011d,
0x011101a4, 0x018601a4, 0x014201a0, 0x010001a3,
0x0101011f);
}
static int rcar_mipi_dsi_post_init_phtw_v3u(struct rcar_mipi_dsi *dsi)
{
return WRITE_PHTW(0x010c0130, 0x010c0140, 0x010c0150, 0x010c0180,
0x010c0190, 0x010a0160, 0x010a0170, 0x01800164,
0x01800174);
}
static int rcar_mipi_dsi_init_phtw_v4h(struct rcar_mipi_dsi *dsi,
const struct dsi_setup_info *setup_info)
{
int ret;
if (setup_info->hsfreq < MHZ(450)) {
ret = WRITE_PHTW(0x01010100, 0x011b01ac);
if (ret)
return ret;
}
ret = WRITE_PHTW(0x01010100, 0x01030173, 0x01000174, 0x01500175,
0x01030176, 0x01040166, 0x010201ad);
if (ret)
return ret;
if (setup_info->hsfreq <= MHZ(1000))
ret = WRITE_PHTW(0x01020100, 0x01910170, 0x01020171,
0x01110172);
else if (setup_info->hsfreq <= MHZ(1500))
ret = WRITE_PHTW(0x01020100, 0x01980170, 0x01030171,
0x01100172);
else if (setup_info->hsfreq <= MHZ(2500))
ret = WRITE_PHTW(0x01020100, 0x0144016b, 0x01000172);
else
return -EINVAL;
if (ret)
return ret;
if (dsi->lanes <= 1) {
ret = WRITE_PHTW(0x01070100, 0x010e010b);
if (ret)
return ret;
}
if (dsi->lanes <= 2) {
ret = WRITE_PHTW(0x01090100, 0x010e010b);
if (ret)
return ret;
}
if (dsi->lanes <= 3) {
ret = WRITE_PHTW(0x010b0100, 0x010e010b);
if (ret)
return ret;
}
if (setup_info->hsfreq <= MHZ(1500)) {
ret = WRITE_PHTW(0x01010100, 0x01c0016e);
if (ret)
return ret;
}
return 0;
}
static int
rcar_mipi_dsi_post_init_phtw_v4h(struct rcar_mipi_dsi *dsi,
const struct dsi_setup_info *setup_info)
{
u32 status;
int ret;
if (setup_info->hsfreq <= MHZ(1500)) {
WRITE_PHTW(0x01020100, 0x00000180);
ret = read_poll_timeout(rcar_mipi_dsi_read, status,
status & PHTR_TEST, 2000, 10000, false,
dsi, PHTR);
if (ret < 0) {
dev_err(dsi->dev, "failed to test PHTR\n");
return ret;
}
WRITE_PHTW(0x01010100, 0x0100016e);
}
return 0;
}
/* -----------------------------------------------------------------------------
* Hardware Setup
*/
struct dsi_setup_info {
unsigned long fout;
u16 vco_cntrl;
u16 prop_cntrl;
u16 hsfreqrange;
u16 div;
unsigned int m;
unsigned int n;
};
static void rcar_mipi_dsi_pll_calc(struct rcar_mipi_dsi *dsi,
unsigned long fin_rate,
unsigned long fout_target,
struct dsi_setup_info *setup_info)
{
unsigned int best_err = -1;
const struct rcar_mipi_dsi_device_info *info = dsi->info;
for (unsigned int n = info->n_min; n <= info->n_max; n++) {
unsigned long fpfd;
fpfd = fin_rate / n;
if (fpfd < info->fpfd_min || fpfd > info->fpfd_max)
continue;
for (unsigned int m = info->m_min; m <= info->m_max; m++) {
unsigned int err;
u64 fout;
fout = div64_u64((u64)fpfd * m, dsi->info->n_mul);
if (fout < info->fout_min || fout > info->fout_max)
continue;
fout = div64_u64(fout, setup_info->vclk_divider);
if (fout < setup_info->clkset->min_freq ||
fout > setup_info->clkset->max_freq)
continue;
err = abs((long)(fout - fout_target) * 10000 /
(long)fout_target);
if (err < best_err) {
setup_info->m = m;
setup_info->n = n;
setup_info->fout = (unsigned long)fout;
best_err = err;
if (err == 0)
return;
}
}
}
}
static void rcar_mipi_dsi_parameters_calc(struct rcar_mipi_dsi *dsi,
struct clk *clk, unsigned long target,
struct dsi_setup_info *setup_info)
{
const struct vco_cntrl_value *vco_cntrl;
const struct dsi_clk_config *clk_cfg;
unsigned long fout_target;
unsigned long fin, fout;
unsigned long hsfreq;
unsigned int best_err = -1;
unsigned int divider;
unsigned int n;
unsigned long fin_rate;
unsigned int i;
unsigned int err;
@ -198,70 +397,53 @@ static void rcar_mipi_dsi_parameters_calc(struct rcar_mipi_dsi *dsi,
*/
fout_target = target * mipi_dsi_pixel_format_to_bpp(dsi->format)
/ (2 * dsi->lanes);
if (fout_target < 40000000 || fout_target > 1250000000)
if (fout_target < MHZ(40) || fout_target > MHZ(1250))
return;
/* Find vco_cntrl */
for (vco_cntrl = vco_cntrl_table; vco_cntrl->min_freq != 0; vco_cntrl++) {
if (fout_target > vco_cntrl->min_freq &&
fout_target <= vco_cntrl->max_freq) {
setup_info->vco_cntrl = vco_cntrl->value;
if (fout_target >= 1150000000)
setup_info->prop_cntrl = 0x0c;
else
setup_info->prop_cntrl = 0x0b;
/* Find PLL settings */
for (clk_cfg = dsi->info->clk_cfg; clk_cfg->min_freq != 0; clk_cfg++) {
if (fout_target > clk_cfg->min_freq &&
fout_target <= clk_cfg->max_freq) {
setup_info->clkset = clk_cfg;
break;
}
}
/* Add divider */
setup_info->div = (setup_info->vco_cntrl & 0x30) >> 4;
fin_rate = clk_get_rate(clk);
switch (dsi->info->model) {
case RCAR_DSI_V3U:
default:
setup_info->vclk_divider = 1 << ((clk_cfg->vco_cntrl >> 4) & 0x3);
break;
case RCAR_DSI_V4H:
setup_info->vclk_divider = 1 << (((clk_cfg->vco_cntrl >> 3) & 0x7) + 1);
break;
}
rcar_mipi_dsi_pll_calc(dsi, fin_rate, fout_target, setup_info);
/* Find hsfreqrange */
hsfreq = fout_target * 2;
setup_info->hsfreq = setup_info->fout * 2;
for (i = 0; i < ARRAY_SIZE(hsfreqrange_table); i++) {
if (hsfreqrange_table[i][0] >= hsfreq) {
if (hsfreqrange_table[i][0] >= setup_info->hsfreq) {
setup_info->hsfreqrange = hsfreqrange_table[i][1];
break;
}
}
/*
* Calculate n and m for PLL clock
* Following the HW manual the ranges of n and m are
* n = [3-8] and m = [64-625]
*/
fin = clk_get_rate(clk);
divider = 1 << setup_info->div;
for (n = 3; n < 9; n++) {
unsigned long fpfd;
unsigned int m;
err = abs((long)(setup_info->fout - fout_target) * 10000 / (long)fout_target);
fpfd = fin / n;
for (m = 64; m < 626; m++) {
fout = fpfd * m / divider;
err = abs((long)(fout - fout_target) * 10000 /
(long)fout_target);
if (err < best_err) {
setup_info->m = m - 2;
setup_info->n = n - 1;
setup_info->fout = fout;
best_err = err;
if (err == 0)
goto done;
}
}
}
done:
dev_dbg(dsi->dev,
"%pC %lu Hz -> Fout %lu Hz (target %lu Hz, error %d.%02u%%), PLL M/N/DIV %u/%u/%u\n",
clk, fin, setup_info->fout, fout_target, best_err / 100,
best_err % 100, setup_info->m, setup_info->n, setup_info->div);
"Fout = %u * %lu / (%u * %u * %u) = %lu (target %lu Hz, error %d.%02u%%)\n",
setup_info->m, fin_rate, dsi->info->n_mul, setup_info->n,
setup_info->vclk_divider, setup_info->fout, fout_target,
err / 100, err % 100);
dev_dbg(dsi->dev,
"vco_cntrl = 0x%x\tprop_cntrl = 0x%x\thsfreqrange = 0x%x\n",
setup_info->vco_cntrl, setup_info->prop_cntrl,
clk_cfg->vco_cntrl, clk_cfg->prop_cntrl,
setup_info->hsfreqrange);
}
@ -324,7 +506,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi,
{
struct dsi_setup_info setup_info = {};
unsigned int timeout;
int ret, i;
int ret;
int dsi_format;
u32 phy_setup;
u32 clockset2, clockset3;
@ -360,10 +542,19 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi,
phy_setup |= PHYSETUP_HSFREQRANGE(setup_info.hsfreqrange);
rcar_mipi_dsi_write(dsi, PHYSETUP, phy_setup);
for (i = 0; i < ARRAY_SIZE(phtw); i++) {
ret = rcar_mipi_dsi_phtw_test(dsi, phtw[i]);
switch (dsi->info->model) {
case RCAR_DSI_V3U:
default:
ret = rcar_mipi_dsi_init_phtw_v3u(dsi);
if (ret < 0)
return ret;
break;
case RCAR_DSI_V4H:
ret = rcar_mipi_dsi_init_phtw_v4h(dsi, &setup_info);
if (ret < 0)
return ret;
break;
}
/* PLL Clock Setting */
@ -371,12 +562,13 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi,
rcar_mipi_dsi_set(dsi, CLOCKSET1, CLOCKSET1_SHADOW_CLEAR);
rcar_mipi_dsi_clr(dsi, CLOCKSET1, CLOCKSET1_SHADOW_CLEAR);
clockset2 = CLOCKSET2_M(setup_info.m) | CLOCKSET2_N(setup_info.n)
| CLOCKSET2_VCO_CNTRL(setup_info.vco_cntrl);
clockset3 = CLOCKSET3_PROP_CNTRL(setup_info.prop_cntrl)
| CLOCKSET3_INT_CNTRL(0)
| CLOCKSET3_CPBIAS_CNTRL(0x10)
| CLOCKSET3_GMP_CNTRL(1);
clockset2 = CLOCKSET2_M(setup_info.m - dsi->info->clockset2_m_offset)
| CLOCKSET2_N(setup_info.n - 1)
| CLOCKSET2_VCO_CNTRL(setup_info.clkset->vco_cntrl);
clockset3 = CLOCKSET3_PROP_CNTRL(setup_info.clkset->prop_cntrl)
| CLOCKSET3_INT_CNTRL(setup_info.clkset->int_cntrl)
| CLOCKSET3_CPBIAS_CNTRL(setup_info.clkset->cpbias_cntrl)
| CLOCKSET3_GMP_CNTRL(setup_info.clkset->gmp_cntrl);
rcar_mipi_dsi_write(dsi, CLOCKSET2, clockset2);
rcar_mipi_dsi_write(dsi, CLOCKSET3, clockset3);
@ -407,10 +599,19 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi,
return -ETIMEDOUT;
}
for (i = 0; i < ARRAY_SIZE(phtw2); i++) {
ret = rcar_mipi_dsi_phtw_test(dsi, phtw2[i]);
switch (dsi->info->model) {
case RCAR_DSI_V3U:
default:
ret = rcar_mipi_dsi_post_init_phtw_v3u(dsi);
if (ret < 0)
return ret;
break;
case RCAR_DSI_V4H:
ret = rcar_mipi_dsi_post_init_phtw_v4h(dsi, &setup_info);
if (ret < 0)
return ret;
break;
}
/* Enable DOT clock */
@ -427,8 +628,19 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi,
dev_warn(dsi->dev, "unsupported format");
return -EINVAL;
}
vclkset |= VCLKSET_COLOR_RGB | VCLKSET_DIV(setup_info.div)
| VCLKSET_LANE(dsi->lanes - 1);
vclkset |= VCLKSET_COLOR_RGB | VCLKSET_LANE(dsi->lanes - 1);
switch (dsi->info->model) {
case RCAR_DSI_V3U:
default:
vclkset |= VCLKSET_DIV_V3U(__ffs(setup_info.vclk_divider));
break;
case RCAR_DSI_V4H:
vclkset |= VCLKSET_DIV_V4H(__ffs(setup_info.vclk_divider) - 1);
break;
}
rcar_mipi_dsi_write(dsi, VCLKSET, vclkset);
@ -841,8 +1053,39 @@ static int rcar_mipi_dsi_remove(struct platform_device *pdev)
return 0;
}
static const struct rcar_mipi_dsi_device_info v3u_data = {
.model = RCAR_DSI_V3U,
.clk_cfg = dsi_clk_cfg_v3u,
.clockset2_m_offset = 2,
.n_min = 3,
.n_max = 8,
.n_mul = 1,
.fpfd_min = MHZ(2),
.fpfd_max = MHZ(8),
.m_min = 64,
.m_max = 625,
.fout_min = MHZ(320),
.fout_max = MHZ(1250),
};
static const struct rcar_mipi_dsi_device_info v4h_data = {
.model = RCAR_DSI_V4H,
.clk_cfg = dsi_clk_cfg_v4h,
.clockset2_m_offset = 0,
.n_min = 1,
.n_max = 8,
.n_mul = 2,
.fpfd_min = MHZ(8),
.fpfd_max = MHZ(24),
.m_min = 167,
.m_max = 1000,
.fout_min = MHZ(2000),
.fout_max = MHZ(4000),
};
static const struct of_device_id rcar_mipi_dsi_of_table[] = {
{ .compatible = "renesas,r8a779a0-dsi-csi2-tx" },
{ .compatible = "renesas,r8a779a0-dsi-csi2-tx", .data = &v3u_data },
{ .compatible = "renesas,r8a779g0-dsi-csi2-tx", .data = &v4h_data },
{ }
};

View File

@ -122,7 +122,8 @@
#define VCLKSET_CKEN (1 << 16)
#define VCLKSET_COLOR_RGB (0 << 8)
#define VCLKSET_COLOR_YCC (1 << 8)
#define VCLKSET_DIV(x) (((x) & 0x3) << 4)
#define VCLKSET_DIV_V3U(x) (((x) & 0x3) << 4)
#define VCLKSET_DIV_V4H(x) (((x) & 0x7) << 4)
#define VCLKSET_BPP_16 (0 << 2)
#define VCLKSET_BPP_18 (1 << 2)
#define VCLKSET_BPP_18L (2 << 2)
@ -166,6 +167,9 @@
#define PHTW_CWEN (1 << 8)
#define PHTW_TESTDIN_CODE(x) (((x) & 0xff) << 0)
#define PHTR 0x1038
#define PHTR_TEST (1 << 16)
#define PHTC 0x103c
#define PHTC_TESTCLR (1 << 0)

View File

@ -818,9 +818,9 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
.wpf_count = 2,
.num_bru_inputs = 5,
}, {
.version = VI6_IP_VERSION_MODEL_VSPD_V3U,
.version = VI6_IP_VERSION_MODEL_VSPD_GEN4,
.model = "VSP2-D",
.gen = 3,
.gen = 4,
.features = VSP1_HAS_BRU | VSP1_HAS_EXT_DL,
.lif_count = 1,
.rpf_count = 5,

View File

@ -196,10 +196,10 @@ struct vsp1_hgo *vsp1_hgo_create(struct vsp1_device *vsp1)
/* Initialize the control handler. */
v4l2_ctrl_handler_init(&hgo->ctrls.handler,
vsp1->info->gen == 3 ? 2 : 1);
vsp1->info->gen >= 3 ? 2 : 1);
hgo->ctrls.max_rgb = v4l2_ctrl_new_custom(&hgo->ctrls.handler,
&hgo_max_rgb_control, NULL);
if (vsp1->info->gen == 3)
if (vsp1->info->gen >= 3)
hgo->ctrls.num_bins =
v4l2_ctrl_new_custom(&hgo->ctrls.handler,
&hgo_num_bins_control, NULL);

View File

@ -114,6 +114,7 @@ static void lif_configure_stream(struct vsp1_entity *entity,
break;
case VI6_IP_VERSION_MODEL_VSPD_GEN3:
case VI6_IP_VERSION_MODEL_VSPD_GEN4:
default:
hbth = 0;
obth = 3000;

View File

@ -146,6 +146,18 @@ static const struct vsp1_format_info vsp1_video_formats[] = {
VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
1, { 32, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_RGBX1010102, MEDIA_BUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB10_RGB10A2_A2RGB10,
VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
1, { 32, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_RGBA1010102, MEDIA_BUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB10_RGB10A2_A2RGB10,
VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
1, { 32, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_ARGB2101010, MEDIA_BUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB10_RGB10A2_A2RGB10,
VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
1, { 32, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_UYVY, MEDIA_BUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
@ -202,6 +214,12 @@ static const struct vsp1_format_info vsp1_video_formats[] = {
VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
3, { 8, 8, 8 }, false, true, 1, 1, false },
{ V4L2_PIX_FMT_Y210, MEDIA_BUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
1, { 32, 0, 0 }, false, false, 2, 1, false },
{ V4L2_PIX_FMT_Y212, MEDIA_BUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
1, { 32, 0, 0 }, false, false, 2, 1, false },
};
/**

View File

@ -228,6 +228,28 @@
#define VI6_RPF_MULT_ALPHA_RATIO_MASK (0xff << 0)
#define VI6_RPF_MULT_ALPHA_RATIO_SHIFT 0
#define VI6_RPF_EXT_INFMT0 0x0370
#define VI6_RPF_EXT_INFMT0_F2B BIT(12)
#define VI6_RPF_EXT_INFMT0_IPBD_Y_8 (0 << 8)
#define VI6_RPF_EXT_INFMT0_IPBD_Y_10 (1 << 8)
#define VI6_RPF_EXT_INFMT0_IPBD_Y_12 (2 << 8)
#define VI6_RPF_EXT_INFMT0_IPBD_C_8 (0 << 4)
#define VI6_RPF_EXT_INFMT0_IPBD_C_10 (1 << 4)
#define VI6_RPF_EXT_INFMT0_IPBD_C_12 (2 << 4)
#define VI6_RPF_EXT_INFMT0_BYPP_M1_RGB10 (3 << 0)
#define VI6_RPF_EXT_INFMT1 0x0374
#define VI6_RPF_EXT_INFMT1_PACK_CPOS(a, b, c, d) \
(((a) << 24) | ((b) << 16) | ((c) << 8) | ((d) << 0))
#define VI6_RPF_EXT_INFMT2 0x0378
#define VI6_RPF_EXT_INFMT2_PACK_CLEN(a, b, c, d) \
(((a) << 24) | ((b) << 16) | ((c) << 8) | ((d) << 0))
#define VI6_RPF_BRDITH_CTRL 0x03e0
#define VI6_RPF_BRDITH_CTRL_ODE BIT(8)
#define VI6_RPF_BRDITH_CTRL_CBRM BIT(0)
/* -----------------------------------------------------------------------------
* WPF Control Registers
*/
@ -766,7 +788,7 @@
#define VI6_IP_VERSION_MODEL_VSPD_V3 (0x18 << 8)
#define VI6_IP_VERSION_MODEL_VSPDL_GEN3 (0x19 << 8)
#define VI6_IP_VERSION_MODEL_VSPBS_GEN3 (0x1a << 8)
#define VI6_IP_VERSION_MODEL_VSPD_V3U (0x1c << 8)
#define VI6_IP_VERSION_MODEL_VSPD_GEN4 (0x1c << 8)
/* RZ/G2L SoCs have no version register, So use 0x80 as the model version */
#define VI6_IP_VERSION_MODEL_VSPD_RZG2L (0x80 << 8)
@ -782,6 +804,7 @@
#define VI6_IP_VERSION_SOC_M3N (0x04 << 0)
#define VI6_IP_VERSION_SOC_E3 (0x04 << 0)
#define VI6_IP_VERSION_SOC_V3U (0x05 << 0)
#define VI6_IP_VERSION_SOC_V4H (0x06 << 0)
/* RZ/G2L SoCs have no version register, So use 0x80 for SoC Identification */
#define VI6_IP_VERSION_SOC_RZG2L (0x80 << 0)
@ -845,6 +868,7 @@
#define VI6_FMT_XBXGXR_262626 0x21
#define VI6_FMT_ABGR_8888 0x22
#define VI6_FMT_XXRGB_88565 0x23
#define VI6_FMT_RGB10_RGB10A2_A2RGB10 0x30
#define VI6_FMT_Y_UV_444 0x40
#define VI6_FMT_Y_UV_422 0x41

View File

@ -109,6 +109,58 @@ static void rpf_configure_stream(struct vsp1_entity *entity,
vsp1_rpf_write(rpf, dlb, VI6_RPF_INFMT, infmt);
vsp1_rpf_write(rpf, dlb, VI6_RPF_DSWAP, fmtinfo->swap);
if (entity->vsp1->info->gen == 4) {
u32 ext_infmt0;
u32 ext_infmt1;
u32 ext_infmt2;
switch (fmtinfo->fourcc) {
case V4L2_PIX_FMT_RGBX1010102:
ext_infmt0 = VI6_RPF_EXT_INFMT0_BYPP_M1_RGB10;
ext_infmt1 = VI6_RPF_EXT_INFMT1_PACK_CPOS(0, 10, 20, 0);
ext_infmt2 = VI6_RPF_EXT_INFMT2_PACK_CLEN(10, 10, 10, 0);
break;
case V4L2_PIX_FMT_RGBA1010102:
ext_infmt0 = VI6_RPF_EXT_INFMT0_BYPP_M1_RGB10;
ext_infmt1 = VI6_RPF_EXT_INFMT1_PACK_CPOS(0, 10, 20, 30);
ext_infmt2 = VI6_RPF_EXT_INFMT2_PACK_CLEN(10, 10, 10, 2);
break;
case V4L2_PIX_FMT_ARGB2101010:
ext_infmt0 = VI6_RPF_EXT_INFMT0_BYPP_M1_RGB10;
ext_infmt1 = VI6_RPF_EXT_INFMT1_PACK_CPOS(2, 12, 22, 0);
ext_infmt2 = VI6_RPF_EXT_INFMT2_PACK_CLEN(10, 10, 10, 2);
break;
case V4L2_PIX_FMT_Y210:
ext_infmt0 = VI6_RPF_EXT_INFMT0_F2B |
VI6_RPF_EXT_INFMT0_IPBD_Y_10 |
VI6_RPF_EXT_INFMT0_IPBD_C_10;
ext_infmt1 = 0x0;
ext_infmt2 = 0x0;
break;
case V4L2_PIX_FMT_Y212:
ext_infmt0 = VI6_RPF_EXT_INFMT0_F2B |
VI6_RPF_EXT_INFMT0_IPBD_Y_12 |
VI6_RPF_EXT_INFMT0_IPBD_C_12;
ext_infmt1 = 0x0;
ext_infmt2 = 0x0;
break;
default:
ext_infmt0 = 0;
ext_infmt1 = 0;
ext_infmt2 = 0;
break;
}
vsp1_rpf_write(rpf, dlb, VI6_RPF_EXT_INFMT0, ext_infmt0);
vsp1_rpf_write(rpf, dlb, VI6_RPF_EXT_INFMT1, ext_infmt1);
vsp1_rpf_write(rpf, dlb, VI6_RPF_EXT_INFMT2, ext_infmt2);
}
/* Output location. */
if (pipe->brx) {
const struct v4l2_rect *compose;
@ -133,18 +185,18 @@ static void rpf_configure_stream(struct vsp1_entity *entity,
* a fixed alpha value set through the V4L2_CID_ALPHA_COMPONENT control
* otherwise.
*
* The Gen3 RPF has extended alpha capability and can both multiply the
* The Gen3+ RPF has extended alpha capability and can both multiply the
* alpha channel by a fixed global alpha value, and multiply the pixel
* components to convert the input to premultiplied alpha.
*
* As alpha premultiplication is available in the BRx for both Gen2 and
* Gen3 we handle it there and use the Gen3 alpha multiplier for global
* Gen3+ we handle it there and use the Gen3 alpha multiplier for global
* alpha multiplication only. This however prevents conversion to
* premultiplied alpha if no BRx is present in the pipeline. If that use
* case turns out to be useful we will revisit the implementation (for
* Gen3 only).
*
* We enable alpha multiplication on Gen3 using the fixed alpha value
* We enable alpha multiplication on Gen3+ using the fixed alpha value
* set through the V4L2_CID_ALPHA_COMPONENT control when the input
* contains an alpha channel. On Gen2 the global alpha is ignored in
* that case.
@ -155,7 +207,7 @@ static void rpf_configure_stream(struct vsp1_entity *entity,
(fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED
: VI6_RPF_ALPH_SEL_ASEL_FIXED));
if (entity->vsp1->info->gen == 3) {
if (entity->vsp1->info->gen >= 3) {
u32 mult;
if (fmtinfo->alpha) {
@ -301,10 +353,10 @@ static void rpf_configure_partition(struct vsp1_entity *entity,
}
/*
* On Gen3 hardware the SPUVS bit has no effect on 3-planar
* On Gen3+ hardware the SPUVS bit has no effect on 3-planar
* formats. Swap the U and V planes manually in that case.
*/
if (vsp1->info->gen == 3 && format->num_planes == 3 &&
if (vsp1->info->gen >= 3 && format->num_planes == 3 &&
fmtinfo->swap_uv)
swap(mem.addr[1], mem.addr[2]);

View File

@ -267,10 +267,10 @@ static int vsp1_video_pipeline_setup_partitions(struct vsp1_pipeline *pipe)
div_size = format->width;
/*
* Only Gen3 hardware requires image partitioning, Gen2 will operate
* Only Gen3+ hardware requires image partitioning, Gen2 will operate
* with a single partition that covers the whole output.
*/
if (vsp1->info->gen == 3) {
if (vsp1->info->gen >= 3) {
list_for_each_entry(entity, &pipe->entities, list_pipe) {
unsigned int entity_max;

View File

@ -512,10 +512,10 @@ static void wpf_configure_partition(struct vsp1_entity *entity,
}
/*
* On Gen3 hardware the SPUVS bit has no effect on 3-planar
* On Gen3+ hardware the SPUVS bit has no effect on 3-planar
* formats. Swap the U and V planes manually in that case.
*/
if (vsp1->info->gen == 3 && format->num_planes == 3 &&
if (vsp1->info->gen >= 3 && format->num_planes == 3 &&
fmtinfo->swap_uv)
swap(mem.addr[1], mem.addr[2]);

View File

@ -1298,6 +1298,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_BGRX32: descr = "32-bit XBGR 8-8-8-8"; break;
case V4L2_PIX_FMT_RGBA32: descr = "32-bit RGBA 8-8-8-8"; break;
case V4L2_PIX_FMT_RGBX32: descr = "32-bit RGBX 8-8-8-8"; break;
case V4L2_PIX_FMT_RGBX1010102: descr = "32-bit RGBX 10-10-10-2"; break;
case V4L2_PIX_FMT_RGBA1010102: descr = "32-bit RGBA 10-10-10-2"; break;
case V4L2_PIX_FMT_ARGB2101010: descr = "32-bit ARGB 2-10-10-10"; break;
case V4L2_PIX_FMT_GREY: descr = "8-bit Greyscale"; break;
case V4L2_PIX_FMT_Y4: descr = "4-bit Greyscale"; break;
case V4L2_PIX_FMT_Y6: descr = "6-bit Greyscale"; break;
@ -1442,6 +1445,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_NV12M_8L128: descr = "NV12M (8x128 Linear)"; break;
case V4L2_PIX_FMT_NV12_10BE_8L128: descr = "10-bit NV12 (8x128 Linear, BE)"; break;
case V4L2_PIX_FMT_NV12M_10BE_8L128: descr = "10-bit NV12M (8x128 Linear, BE)"; break;
case V4L2_PIX_FMT_Y210: descr = "10-bit YUYV Packed"; break;
case V4L2_PIX_FMT_Y212: descr = "12-bit YUYV Packed"; break;
case V4L2_PIX_FMT_Y216: descr = "16-bit YUYV Packed"; break;
default:
/* Compressed formats */

View File

@ -576,6 +576,9 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_RGBX32 v4l2_fourcc('X', 'B', '2', '4') /* 32 RGBX-8-8-8-8 */
#define V4L2_PIX_FMT_ARGB32 v4l2_fourcc('B', 'A', '2', '4') /* 32 ARGB-8-8-8-8 */
#define V4L2_PIX_FMT_XRGB32 v4l2_fourcc('B', 'X', '2', '4') /* 32 XRGB-8-8-8-8 */
#define V4L2_PIX_FMT_RGBX1010102 v4l2_fourcc('R', 'X', '3', '0') /* 32 RGBX-10-10-10-2 */
#define V4L2_PIX_FMT_RGBA1010102 v4l2_fourcc('R', 'A', '3', '0') /* 32 RGBA-10-10-10-2 */
#define V4L2_PIX_FMT_ARGB2101010 v4l2_fourcc('A', 'R', '3', '0') /* 32 ARGB-2-10-10-10 */
/* Grey formats */
#define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */
@ -618,6 +621,14 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_YUVX32 v4l2_fourcc('Y', 'U', 'V', 'X') /* 32 YUVX-8-8-8-8 */
#define V4L2_PIX_FMT_M420 v4l2_fourcc('M', '4', '2', '0') /* 12 YUV 4:2:0 2 lines y, 1 line uv interleaved */
/*
* YCbCr packed format. For each Y2xx format, xx bits of valid data occupy the MSBs
* of the 16 bit components, and 16-xx bits of zero padding occupy the LSBs.
*/
#define V4L2_PIX_FMT_Y210 v4l2_fourcc('Y', '2', '1', '0') /* 32 YUYV 4:2:2 */
#define V4L2_PIX_FMT_Y212 v4l2_fourcc('Y', '2', '1', '2') /* 32 YUYV 4:2:2 */
#define V4L2_PIX_FMT_Y216 v4l2_fourcc('Y', '2', '1', '6') /* 32 YUYV 4:2:2 */
/* two planes -- one Y, one Cr + Cb interleaved */
#define V4L2_PIX_FMT_NV12 v4l2_fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */
#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N', 'V', '2', '1') /* 12 Y/CrCb 4:2:0 */