2018-07-26 09:37:32 +07:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
2013-06-19 18:54:11 +07:00
|
|
|
/*
|
|
|
|
* rcar_du_drv.h -- R-Car Display Unit DRM driver
|
|
|
|
*
|
2015-09-07 21:34:26 +07:00
|
|
|
* Copyright (C) 2013-2015 Renesas Electronics Corporation
|
2013-06-19 18:54:11 +07:00
|
|
|
*
|
|
|
|
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __RCAR_DU_DRV_H__
|
|
|
|
#define __RCAR_DU_DRV_H__
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
2015-02-23 06:02:15 +07:00
|
|
|
#include <linux/wait.h>
|
2013-06-19 18:54:11 +07:00
|
|
|
|
|
|
|
#include "rcar_du_crtc.h"
|
2013-06-17 02:01:02 +07:00
|
|
|
#include "rcar_du_group.h"
|
2015-09-07 21:14:58 +07:00
|
|
|
#include "rcar_du_vsp.h"
|
2013-06-19 18:54:11 +07:00
|
|
|
|
|
|
|
struct clk;
|
|
|
|
struct device;
|
|
|
|
struct drm_device;
|
2018-12-27 16:26:56 +07:00
|
|
|
struct drm_property;
|
2013-06-17 02:01:02 +07:00
|
|
|
struct rcar_du_device;
|
2019-01-17 06:59:34 +07:00
|
|
|
struct rcar_du_encoder;
|
2013-06-19 18:54:11 +07:00
|
|
|
|
2018-08-20 23:00:43 +07:00
|
|
|
#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK BIT(0) /* Per-CRTC IRQ and clock */
|
2018-11-25 00:57:17 +07:00
|
|
|
#define RCAR_DU_FEATURE_VSP1_SOURCE BIT(1) /* Has inputs from VSP1 */
|
|
|
|
#define RCAR_DU_FEATURE_INTERLACED BIT(2) /* HW supports interlaced */
|
|
|
|
#define RCAR_DU_FEATURE_TVM_SYNC BIT(3) /* Has TV switch/sync modes */
|
2013-11-13 19:33:45 +07:00
|
|
|
|
2018-08-20 23:00:43 +07:00
|
|
|
#define RCAR_DU_QUIRK_ALIGN_128B BIT(0) /* Align pitches to 128 bytes */
|
2013-06-14 19:15:01 +07:00
|
|
|
|
2013-06-17 08:13:11 +07:00
|
|
|
/*
|
|
|
|
* struct rcar_du_output_routing - Output routing specification
|
|
|
|
* @possible_crtcs: bitmask of possible CRTCs for the output
|
2014-01-21 21:57:26 +07:00
|
|
|
* @port: device tree port number corresponding to this output route
|
2013-06-17 08:13:11 +07:00
|
|
|
*
|
|
|
|
* The DU has 5 possible outputs (DPAD0/1, LVDS0/1, TCON). Output routing data
|
|
|
|
* specify the valid SoC outputs, which CRTCs can drive the output, and the type
|
|
|
|
* of in-SoC encoder for the output.
|
|
|
|
*/
|
|
|
|
struct rcar_du_output_routing {
|
|
|
|
unsigned int possible_crtcs;
|
2014-01-21 21:57:26 +07:00
|
|
|
unsigned int port;
|
2013-06-17 08:13:11 +07:00
|
|
|
};
|
|
|
|
|
2013-06-14 18:38:33 +07:00
|
|
|
/*
|
|
|
|
* struct rcar_du_device_info - DU model-specific information
|
2015-09-07 21:34:26 +07:00
|
|
|
* @gen: device generation (2 or 3)
|
2013-06-14 18:38:33 +07:00
|
|
|
* @features: device features (RCAR_DU_FEATURE_*)
|
2013-11-13 19:33:45 +07:00
|
|
|
* @quirks: device quirks (RCAR_DU_QUIRK_*)
|
2018-04-28 05:21:52 +07:00
|
|
|
* @channels_mask: bit mask of available DU channels
|
2013-06-17 08:13:11 +07:00
|
|
|
* @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
|
2013-06-17 18:48:27 +07:00
|
|
|
* @num_lvds: number of internal LVDS encoders
|
2018-08-22 14:21:47 +07:00
|
|
|
* @dpll_mask: bit mask of DU channels equipped with a DPLL
|
drm: rcar-du: Use LVDS PLL clock as dot clock when possible
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>
2018-08-22 01:31:04 +07:00
|
|
|
* @lvds_clk_mask: bitmask of channels that can use the LVDS clock as dot clock
|
2013-06-14 18:38:33 +07:00
|
|
|
*/
|
|
|
|
struct rcar_du_device_info {
|
2015-09-07 21:34:26 +07:00
|
|
|
unsigned int gen;
|
2013-06-14 18:38:33 +07:00
|
|
|
unsigned int features;
|
2013-11-13 19:33:45 +07:00
|
|
|
unsigned int quirks;
|
2018-04-28 05:21:52 +07:00
|
|
|
unsigned int channels_mask;
|
2013-06-17 08:13:11 +07:00
|
|
|
struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
|
2013-06-17 18:48:27 +07:00
|
|
|
unsigned int num_lvds;
|
2018-08-22 14:21:47 +07:00
|
|
|
unsigned int dpll_mask;
|
drm: rcar-du: Use LVDS PLL clock as dot clock when possible
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>
2018-08-22 01:31:04 +07:00
|
|
|
unsigned int lvds_clk_mask;
|
2013-06-14 18:38:33 +07:00
|
|
|
};
|
|
|
|
|
2015-09-04 17:49:05 +07:00
|
|
|
#define RCAR_DU_MAX_CRTCS 4
|
2015-02-25 23:21:12 +07:00
|
|
|
#define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
|
2015-09-07 21:14:58 +07:00
|
|
|
#define RCAR_DU_MAX_VSPS 4
|
2015-02-25 23:21:12 +07:00
|
|
|
|
2013-06-19 18:54:11 +07:00
|
|
|
struct rcar_du_device {
|
|
|
|
struct device *dev;
|
2013-06-14 18:38:33 +07:00
|
|
|
const struct rcar_du_device_info *info;
|
2013-06-19 18:54:11 +07:00
|
|
|
|
|
|
|
void __iomem *mmio;
|
|
|
|
|
|
|
|
struct drm_device *ddev;
|
|
|
|
|
2015-02-25 23:21:12 +07:00
|
|
|
struct rcar_du_crtc crtcs[RCAR_DU_MAX_CRTCS];
|
2013-06-19 18:54:11 +07:00
|
|
|
unsigned int num_crtcs;
|
|
|
|
|
2019-01-17 06:59:34 +07:00
|
|
|
struct rcar_du_encoder *encoders[RCAR_DU_OUTPUT_MAX];
|
|
|
|
|
2015-02-25 23:21:12 +07:00
|
|
|
struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
|
2015-09-07 21:14:58 +07:00
|
|
|
struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS];
|
2013-06-17 08:20:08 +07:00
|
|
|
|
2015-04-29 03:59:29 +07:00
|
|
|
struct {
|
|
|
|
struct drm_property *colorkey;
|
|
|
|
} props;
|
|
|
|
|
2013-06-17 08:20:08 +07:00
|
|
|
unsigned int dpad0_source;
|
2018-11-25 01:19:52 +07:00
|
|
|
unsigned int dpad1_source;
|
2013-06-21 22:54:50 +07:00
|
|
|
unsigned int vspd1_sink;
|
2013-06-19 18:54:11 +07:00
|
|
|
};
|
|
|
|
|
2013-06-14 18:38:33 +07:00
|
|
|
static inline bool rcar_du_has(struct rcar_du_device *rcdu,
|
|
|
|
unsigned int feature)
|
|
|
|
{
|
|
|
|
return rcdu->info->features & feature;
|
|
|
|
}
|
|
|
|
|
2013-11-13 19:33:45 +07:00
|
|
|
static inline bool rcar_du_needs(struct rcar_du_device *rcdu,
|
|
|
|
unsigned int quirk)
|
|
|
|
{
|
|
|
|
return rcdu->info->quirks & quirk;
|
|
|
|
}
|
|
|
|
|
2013-06-19 18:54:11 +07:00
|
|
|
static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg)
|
|
|
|
{
|
|
|
|
return ioread32(rcdu->mmio + reg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void rcar_du_write(struct rcar_du_device *rcdu, u32 reg, u32 data)
|
|
|
|
{
|
|
|
|
iowrite32(data, rcdu->mmio + reg);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* __RCAR_DU_DRV_H__ */
|