On the D3 and E3 SoCs the LVDS PLL clock output provides the dot clock
to the DU channels, even when the LVDS outputs are not in use. Enable
and disable the LVDS clock output when enabling or disabling a CRTC
connected to the DPAD0 output.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
On the D3 and E3 platforms, the LVDS internal PLL supplies the pixel
clock to the DU. This works automatically for LVDS outputs as the LVDS
encoder is enabled through the bridge API, enabling the internal PLL and
clock output. However, when using the DU DPAD output with the LVDS
outputs turned off, the LVDS PLL needs to be controlled manually. Add an
API to do so, to be called by the DU driver.
The drivers/gpu/drm/rcar-du/ directory has to be treated as obj-y
unconditionally, as the LVDS driver could be built-in while the DU
driver is compiled as a module.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
On the D3 and E3 SoCs the LVDS encoder has an extended internal PLL and
supplies a clock to the DU. That clock is used not only for the LVDS
outputs but also for the DPAD output. The LVDS encoder thus needs to be
available to the DU even when its output is disabled. Don't fail probe
in that case on D3 and E3.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Before the driver fully moved to drm_bridge and drm_panel, it was
necessary to parse DT and locate encoder and connector nodes. The
connector node is now unused and can be removed as a parameter to
rcar_du_encoder_init(). As a consequence rcar_du_encoders_init_one() can
be greatly simplified, removing most of the DT parsing.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Add an of_node_put when the result of of_graph_get_remote_port_parent is
not available.
Add a second of_node_put if no encoder is selected (encoder remains NULL).
The semantic match that finds the first problem is as follows
(http://coccinelle.lip6.fr):
// <smpl>
@r exists@
local idexpression e;
expression x;
@@
e = of_graph_get_remote_port_parent(...);
... when != x = e
when != true e == NULL
when != of_node_put(e)
when != of_fwnode_handle(e)
(
return e;
|
*return ...;
)
// </smpl>
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drm-misc-next for 5.1:
UAPI Changes:
- New fourcc identifier for ARM Framebuffer Compression v1.3
Cross-subsystem Changes:
Core Changes:
- Reorganisation of drm_device and drm_framebuffer headers
- Cleanup of the drmP inclusion
- Fix leaks in the fb-helpers
- Allow for depth different from bpp in fb-helper fbdev emulation
- Remove drm_mode_object from drm_display_mode
Driver Changes:
- Add reflection properties to rockchip
- a bunch of fixes for virtio
- a bunch of fixes for dp_mst and drivers using it, and introduction of a
new refcounting scheme
- Convertion of bochs to atomic and generic fbdev emulation
- Allow meson to remove the firmware framebuffers
[airlied: patch rcar-du to add drm_modes.h]
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maxime Ripard <maxime.ripard@bootlin.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190116200428.u2n4jbk4mzza7n6e@flea
The DRM kernel API used to be defined in a handful of headers, pulled in
through drmP.h. It has since been split in multiple headers for the
different DRM components, and drmP.h turned into a legacy header that
just pulls in most of the DRM kernel API (and a large number of other
miscellaneous kernel headers).
In order to speed up compilation, replace inclusion of drmP.h with only
the required headers. It turns out that the rcar-du-drm driver already
includes most of the necessary headers, so the change is simple.
While at it, remove unneeded inclusion of other headers, and unneeded
forward declarations of structures.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
DU channels are routed to DPAD outputs in an SoC-dependent way. The
routing can be fixed (e.g. DU3 to DPAD0 on H3) or configurable (e.g. DU0
or DU1 to DPAD0 on D3/E3). The hardware offers no option to disconnect
DPAD outputs, which are thus always driven by a DU channel.
On SoCs that have less DU channels than DU outputs, such as D3 and E3,
the DPAD output is always driven when all channels are in use by other
outputs (such as the internal LVDS and HDMI encoders). This creates an
unwanted clone on the DPAD output.
However, the parallel output of the DU channels routed to DPAD can be
set to fixed levels in the DU channels themselves through the DOFLR
group register. Use this to turn the DPAD on or off by driving fixed
signals at the output of any DU channel not routed to a DPAD output.
This doesn't affect the DU output signals going to other outputs.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
The rcar_du_crtc outputs field stores a bitmask of the outputs driven by
the CRTC. This changes based on the configuration requested by
userspace, and is used for the sole purpose of configuring the hardware.
The field thus belongs to the CRTC state. Move it to the
rcar_du_crtc_state structure.
As a result the rcar_du_crtc_route_output() function loses most of its
purpose. In order to remove it, move dpad0_source calculation to
rcar_du_atomic_commit_tail(), until the field gets moved to a state
structure. In order to simplify the rcar_du_group_set_routing()
implementation, we also store the DPAD1 source in a new dpad1_source
field which will move to a state structure with dpad0_source.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
The RCAR_DU_FEATURE_EXT_CTRL_REGS feature flag is missing for H1 only,
which is a first generation device, not a second generation device as
reported in the device information table. Fix the H1 generation and use
generation checks to replace the feature flag.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
The mode and ajusted_mode passed to the bridge .mode_set() operation
should never be modified by the bridge (and are not in any of the
existing bridge drivers). Make them const to make this clear.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drm-next has been forwarded to 5.0-rc1, and we need it to apply the damage
helper for dirtyfb series from Noralf Trønnes.
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
The CMA helper is already using the drm_fb_helper_generic_probe part of
the generic fbdev emulation. This patch makes full use of the generic
fbdev emulation by using its drm_client callbacks. This means that
drm_mode_config_funcs->output_poll_changed and drm_driver->lastclose are
now handled by the emulation code. Additionally fbdev unregister happens
automatically on drm_dev_unregister().
The drm_fbdev_generic_setup() call is put after drm_dev_register() in the
driver. This is done to highlight the fact that fbdev emulation is an
internal client that makes use of the driver, it is not part of the
driver as such. If fbdev setup fails, an error is printed, but the driver
succeeds probing.
drm_fbdev_generic_setup() handles mode_config.num_connector being zero.
In that case it retries fbdev setup on the next .output_poll_changed.
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181128212713.43500-4-noralf@tronnes.org
Group start/stop is controlled by the DRES and DEN bits of DSYSR0 for
the first group and DSYSR2 for the second group. On most DU instances,
this maps to the first CRTC of the group. On M3-N, however, DU2 doesn't
exist, but DSYSR2 does. There is no CRTC object there that maps to the
correct DSYSR register.
Commit 9144adc5e5 ("drm: rcar-du: Cache DSYSR value to ensure known
initial value") switched group start/stop from using group read/write
access to DSYSR to a CRTC-based API to cache the DSYSR value. While
doing so, it introduced a regression on M3-N by accessing DSYSR3 instead
of DSYSR2 to start/stop the second group.
To fix this, access the DSYSR register directly through group read/write
if the SoC is missing the first DU channel of the group. Keep using the
rcar_du_crtc_dsysr_clr_set() function otherwise, to retain the DSYSR
caching feature.
Fixes: 9144adc5e5 ("drm: rcar-du: Cache DSYSR value to ensure known initial value")
Reported-by: Hoan Nguyen An <na-hoan@jinso.co.jp>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Tested-by: Simon Horman <horms+renesas@verge.net.au>
The hardware requires the HDSR and VDSR registers to be set to 1 or
higher. This translates to a minimum combined horizontal sync and back
porch of 20 pixels and a minimum vertical back porch of 3 lines. Reject
modes that fail those requirements.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
The rcar-du driver supports probe deferral for external clocks, but
implements it badly by checking the wrong pointer due to a bad copy and
paste. Fix it.
While at it, reject invalid clocks outright for DU channels that have a
display PLL, as the external clock is mandatory in that case. This
avoids a WARN_ON() at runtime.
Fixes: 1b30dbde85 ("drm: rcar-du: Add support for external pixel clock")
Reported-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Add support for the R-Car M3-N (R8A77965) SoC to the LVDS encoder
driver. The encoder appears identical to the M3-W version, we can thus
simply point to the generic Gen3 data.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
The official way to stop the display is to clear the display enable
(DEN) bit in the DSYSR register, but that operates at a group level and
affects the two channels in the group. To disable channels selectively,
the driver uses TV sync mode that stops display operation on the channel
and turns output signals into inputs.
While TV sync mode is available in all DU models currently supported,
the D3 and E3 DUs don't support it. We will thus need to find an
alternative way to turn channels off.
In the meantime, condition the switch to TV sync mode to the
availability of the feature, to avoid writing an invalid value to the
DSYSR register. When the feature is unavailable the display output will
turn blank as all planes are disabled when stopping the CRTC.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
DSYSR is a DU channel register that also contains group fields. It is
thus written to by both the group and CRTC code, using read-update-write
sequences. As the register isn't initialized explicitly at startup time,
this can lead to invalid or otherwise unexpected values being written to
some of the fields if they have been modified by the firmware or just
not reset properly.
To fix this we can write a fully known value to the DSYSR register when
turning a channel's functional clock on. However, the mix of group and
channel fields complicate this. A simpler solution is to cache the
register and initialize the cached value to the desired hardware
defaults.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
All Gen3 SoCs supported so far have a fixed association between DPAD0
and DU channels, which led to hardcoding that association when writing
the corresponding hardware register. The D3 and E3 will break that
mechanism as DPAD0 can be dynamically connected to either DU0 or DU1.
Make DPAD0 routing dynamic on Gen3. To ensure a valid hardware
configuration when the DU starts without the RGB output enabled, DPAD0
is associated at initialization time to the first DU channel that it can
be connected to. This makes no change on Gen2 as all Gen2 SoCs can
connected DPAD0 to DU0, which is the current implicit default value.
As the DPAD0 source is always 0 when a single source is possible on
Gen2, we can also simplify the Gen2 code in the same function to remove
a conditional check.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
On selected SoCs, the DU can use the clock output by the LVDS encoder
PLL as its input dot clock. This feature is optional, but on the D3 and
E3 SoC it is often the only way to obtain a precise dot clock frequency,
as the other available clocks (CPG-generated clock and external clock)
usually have fixed rates.
Add a DU model information field to describe which DU channels can use
the LVDS PLL output clock as their input clock, and configure clock
routing accordingly.
This feature is available on H2, M2-W, M2-N, D3 and E3 SoCs, with D3 and
E3 being the primary targets. It is left disabled in this commit, and
will be enabled per-SoC after careful testing.
At the hardware level, clock routing is configured at runtime in two
steps, first selecting an internal dot clock between the LVDS PLL clock
and the external DOTCLKIN clock, and then selecting between the internal
dot clock and the CPG-generated clock. The first part requires stopping
the whole DU group in order for the change to take effect, thus causing
flickering on the screen. For this reason we currently hardcode the
clock source to the LVDS PLL clock if available, and allow flicker-free
selection of the external DOTCLKIN clock or CPG-generated clock
otherwise. A more dynamic clock selection process can be implemented
later if the need arises.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
The rcar_du_crtc_get() function is always immediately followed by a call
to rcar_du_crtc_setup(). Call the later from the former to simplify the
code, and add a comment to explain how the get and put calls are
balanced.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
The LVDS encoders in the D3 and E3 SoCs differ significantly from those
in the other R-Car Gen3 family members:
- The LVDS PLL architecture is more complex and requires computing PLL
parameters manually.
- The PLL uses external clocks as inputs, which need to be retrieved
from DT.
- In addition to the different PLL setup, the startup sequence has
changed *again* (seems someone had trouble making his/her mind).
Supporting all this requires DT bindings extensions for external clocks,
brand new PLL setup code, and a few quirks to handle the differences in
the startup sequence.
The implementation doesn't support all hardware features yet, namely
- Using the LV[01] clocks generated by the CPG as PLL input.
- Providing the LVDS PLL clock to the DU for use with the RGB output.
Those features can be added later when the need will arise.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Ulrich Hecht <uli+renesas@fpond.eu>
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
The Gen3 VSP used by the DU for display does not support the packed VYUY
pixel format. Gen2 VSP hardware is able to process this format, but
DU + VSP operation isn't enabled on Gen2, and VYUY isn't a strategic
format, so it can be ignored.
Remove the format from the capabilities of the DU driver.
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
The framebuffer pitch and alignment constraints reflect the limitations
of the Gen2 DU hardware. On Gen3, the DU has no memory interface and
thus doesn't impose any constraint. The limitations come instead from
the VSP that has a limit of 65535 bytes for the pitch and no alignment
constraint. Update the checks accordingly.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
The ESCR and OTAR registers exist in each DU channel, but at different
offsets for odd and even channels. This led to usage of the group
register access API to write them, with offsets macros named ESCR/OTAR
and ESCR2/OTAR2 for the first and second ESCR/OTAR register in the group
respectively.
The names are confusing as it suggests that the ESCR/OTAR registers for
DU0 and DU2 are taken into account, especially with writes performed to
the group register access API.
Rename the offsets to ESCR/OTAR02 and ESCR/OTAR13, and use the CRTC
register access API to clarify the code. The offsets values are updated
accordingly.
Cosmetic patch, no functional changes intended.
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
[Squashed ESCR and OTAR changes in a single commit]
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>