mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
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:
commit
54587d9943
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
======================
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
@ -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 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 },
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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]);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user