Commit 32030592 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'du-next-20220907' of git://linuxtv.org/pinchartl/media into drm-next

- Misc fixes and improvements to the R-Car DU driver
- Synopsys DW HDMI bridge DT bindings update
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/YxkL+tRI8uXDCvj9@pendragon.ideasonboard.com
parents 849b1f33 cee3e583
...@@ -38,6 +38,9 @@ properties: ...@@ -38,6 +38,9 @@ properties:
clock-names: clock-names:
maxItems: 2 maxItems: 2
resets:
maxItems: 1
ports: ports:
$ref: /schemas/graph.yaml#/properties/ports $ref: /schemas/graph.yaml#/properties/ports
...@@ -67,6 +70,7 @@ required: ...@@ -67,6 +70,7 @@ required:
- reg - reg
- clocks - clocks
- clock-names - clock-names
- resets
- interrupts - interrupts
- ports - ports
...@@ -85,6 +89,7 @@ examples: ...@@ -85,6 +89,7 @@ examples:
clocks = <&cpg CPG_CORE R8A7795_CLK_S0D4>, <&cpg CPG_MOD 729>; clocks = <&cpg CPG_CORE R8A7795_CLK_S0D4>, <&cpg CPG_MOD 729>;
clock-names = "iahb", "isfr"; clock-names = "iahb", "isfr";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 729>;
ports { ports {
#address-cells = <1>; #address-cells = <1>;
......
...@@ -14,10 +14,3 @@ obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o ...@@ -14,10 +14,3 @@ obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o
obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o
obj-$(CONFIG_DRM_RCAR_LVDS) += rcar_lvds.o obj-$(CONFIG_DRM_RCAR_LVDS) += rcar_lvds.o
obj-$(CONFIG_DRM_RCAR_MIPI_DSI) += rcar_mipi_dsi.o obj-$(CONFIG_DRM_RCAR_MIPI_DSI) += rcar_mipi_dsi.o
# 'remote-endpoint' is fixed up at run-time
DTC_FLAGS_rcar_du_of_lvds_r8a7790 += -Wno-graph_endpoint
DTC_FLAGS_rcar_du_of_lvds_r8a7791 += -Wno-graph_endpoint
DTC_FLAGS_rcar_du_of_lvds_r8a7793 += -Wno-graph_endpoint
DTC_FLAGS_rcar_du_of_lvds_r8a7795 += -Wno-graph_endpoint
DTC_FLAGS_rcar_du_of_lvds_r8a7796 += -Wno-graph_endpoint
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "rcar_du_regs.h" #include "rcar_du_regs.h"
#include "rcar_du_vsp.h" #include "rcar_du_vsp.h"
#include "rcar_lvds.h" #include "rcar_lvds.h"
#include "rcar_mipi_dsi.h"
static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg) static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
{ {
...@@ -744,7 +745,19 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, ...@@ -744,7 +745,19 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
const struct drm_display_mode *mode = const struct drm_display_mode *mode =
&crtc->state->adjusted_mode; &crtc->state->adjusted_mode;
rcar_lvds_clk_enable(bridge, mode->clock * 1000); rcar_lvds_pclk_enable(bridge, mode->clock * 1000);
}
/*
* Similarly to LVDS, on V3U the dot clock is provided by the DSI
* encoder, and we need to enable the DSI clocks before enabling the CRTC.
*/
if ((rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) &&
(rstate->outputs &
(BIT(RCAR_DU_OUTPUT_DSI0) | BIT(RCAR_DU_OUTPUT_DSI1)))) {
struct drm_bridge *bridge = rcdu->dsi[rcrtc->index];
rcar_mipi_dsi_pclk_enable(bridge, state);
} }
rcar_du_crtc_start(rcrtc); rcar_du_crtc_start(rcrtc);
...@@ -777,7 +790,20 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, ...@@ -777,7 +790,20 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
* Disable the LVDS clock output, see * Disable the LVDS clock output, see
* rcar_du_crtc_atomic_enable(). * rcar_du_crtc_atomic_enable().
*/ */
rcar_lvds_clk_disable(bridge); rcar_lvds_pclk_disable(bridge);
}
if ((rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) &&
(rstate->outputs &
(BIT(RCAR_DU_OUTPUT_DSI0) | BIT(RCAR_DU_OUTPUT_DSI1)))) {
struct drm_bridge *bridge = rcdu->dsi[rcrtc->index];
/*
* Disable the DSI clock output, see
* rcar_du_crtc_atomic_enable().
*/
rcar_mipi_dsi_pclk_disable(bridge);
} }
spin_lock_irq(&crtc->dev->event_lock); spin_lock_irq(&crtc->dev->event_lock);
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "rcar_du_drv.h" #include "rcar_du_drv.h"
#include "rcar_du_kms.h" #include "rcar_du_kms.h"
#include "rcar_du_regs.h"
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Device Information * Device Information
...@@ -507,7 +506,8 @@ static const struct rcar_du_device_info rcar_du_r8a7799x_info = { ...@@ -507,7 +506,8 @@ static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
static const struct rcar_du_device_info rcar_du_r8a779a0_info = { static const struct rcar_du_device_info rcar_du_r8a779a0_info = {
.gen = 3, .gen = 3,
.features = RCAR_DU_FEATURE_CRTC_IRQ .features = RCAR_DU_FEATURE_CRTC_IRQ
| RCAR_DU_FEATURE_VSP1_SOURCE, | RCAR_DU_FEATURE_VSP1_SOURCE
| RCAR_DU_FEATURE_NO_BLENDING,
.channels_mask = BIT(1) | BIT(0), .channels_mask = BIT(1) | BIT(0),
.routes = { .routes = {
/* R8A779A0 has two MIPI DSI outputs. */ /* R8A779A0 has two MIPI DSI outputs. */
......
...@@ -31,6 +31,7 @@ struct rcar_du_device; ...@@ -31,6 +31,7 @@ struct rcar_du_device;
#define RCAR_DU_FEATURE_VSP1_SOURCE BIT(2) /* Has inputs from VSP1 */ #define RCAR_DU_FEATURE_VSP1_SOURCE BIT(2) /* Has inputs from VSP1 */
#define RCAR_DU_FEATURE_INTERLACED BIT(3) /* HW supports interlaced */ #define RCAR_DU_FEATURE_INTERLACED BIT(3) /* HW supports interlaced */
#define RCAR_DU_FEATURE_TVM_SYNC BIT(4) /* Has TV switch/sync modes */ #define RCAR_DU_FEATURE_TVM_SYNC BIT(4) /* Has TV switch/sync modes */
#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_ALIGN_128B BIT(0) /* Align pitches to 128 bytes */
...@@ -91,6 +92,7 @@ struct rcar_du_device_info { ...@@ -91,6 +92,7 @@ struct rcar_du_device_info {
#define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2) #define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
#define RCAR_DU_MAX_VSPS 4 #define RCAR_DU_MAX_VSPS 4
#define RCAR_DU_MAX_LVDS 2 #define RCAR_DU_MAX_LVDS 2
#define RCAR_DU_MAX_DSI 2
struct rcar_du_device { struct rcar_du_device {
struct device *dev; struct device *dev;
...@@ -107,6 +109,7 @@ struct rcar_du_device { ...@@ -107,6 +109,7 @@ struct rcar_du_device {
struct platform_device *cmms[RCAR_DU_MAX_CRTCS]; struct platform_device *cmms[RCAR_DU_MAX_CRTCS];
struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS]; struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS];
struct drm_bridge *lvds[RCAR_DU_MAX_LVDS]; struct drm_bridge *lvds[RCAR_DU_MAX_LVDS];
struct drm_bridge *dsi[RCAR_DU_MAX_DSI];
struct { struct {
struct drm_property *colorkey; struct drm_property *colorkey;
......
...@@ -9,18 +9,13 @@ ...@@ -9,18 +9,13 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/slab.h>
#include <drm/drm_bridge.h> #include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h> #include <drm/drm_bridge_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_managed.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include "rcar_du_drv.h" #include "rcar_du_drv.h"
#include "rcar_du_encoder.h" #include "rcar_du_encoder.h"
#include "rcar_du_kms.h"
#include "rcar_lvds.h" #include "rcar_lvds.h"
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
...@@ -84,6 +79,10 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, ...@@ -84,6 +79,10 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
if (output == RCAR_DU_OUTPUT_LVDS0 || if (output == RCAR_DU_OUTPUT_LVDS0 ||
output == RCAR_DU_OUTPUT_LVDS1) output == RCAR_DU_OUTPUT_LVDS1)
rcdu->lvds[output - RCAR_DU_OUTPUT_LVDS0] = bridge; rcdu->lvds[output - RCAR_DU_OUTPUT_LVDS0] = bridge;
if (output == RCAR_DU_OUTPUT_DSI0 ||
output == RCAR_DU_OUTPUT_DSI1)
rcdu->dsi[output - RCAR_DU_OUTPUT_DSI0] = bridge;
} }
/* /*
......
...@@ -405,8 +405,8 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv, ...@@ -405,8 +405,8 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
format = rcar_du_format_info(mode_cmd->pixel_format); format = rcar_du_format_info(mode_cmd->pixel_format);
if (format == NULL) { if (format == NULL) {
dev_dbg(dev->dev, "unsupported pixel format %08x\n", dev_dbg(dev->dev, "unsupported pixel format %p4cc\n",
mode_cmd->pixel_format); &mode_cmd->pixel_format);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
......
...@@ -506,8 +506,15 @@ static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp, ...@@ -506,8 +506,15 @@ static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp,
unsigned int index, unsigned int index,
const struct rcar_du_plane_state *state) const struct rcar_du_plane_state *state)
{ {
rcar_du_plane_write(rgrp, index, PnMR, struct rcar_du_device *rcdu = rgrp->dev;
PnMR_SPIM_TP_OFF | state->format->pnmr); u32 pnmr = state->format->pnmr | PnMR_SPIM_TP_OFF;
if (rcdu->info->features & RCAR_DU_FEATURE_NO_BLENDING) {
/* No blending. ALP and EOR are not supported. */
pnmr &= ~(PnMR_SPIM_ALP | PnMR_SPIM_EOR);
}
rcar_du_plane_write(rgrp, index, PnMR, pnmr);
rcar_du_plane_write(rgrp, index, PnDDCR4, rcar_du_plane_write(rgrp, index, PnDDCR4,
state->format->edf | PnDDCR4_CODE); state->format->edf | PnDDCR4_CODE);
...@@ -521,7 +528,6 @@ static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp, ...@@ -521,7 +528,6 @@ static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp,
* register to 0 to avoid this. * register to 0 to avoid this.
*/ */
/* TODO: Check if alpha-blending should be disabled in PnMR. */
rcar_du_plane_write(rgrp, index, PnALPHAR, 0); rcar_du_plane_write(rgrp, index, PnALPHAR, 0);
} }
...@@ -619,8 +625,8 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane, ...@@ -619,8 +625,8 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane,
*format = rcar_du_format_info(state->fb->format->format); *format = rcar_du_format_info(state->fb->format->format);
if (*format == NULL) { if (*format == NULL) {
dev_dbg(dev->dev, "%s: unsupported format %08x\n", __func__, dev_dbg(dev->dev, "%s: unsupported format %p4cc\n", __func__,
state->fb->format->format); &state->fb->format->format);
return -EINVAL; return -EINVAL;
} }
......
...@@ -152,6 +152,7 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) ...@@ -152,6 +152,7 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
.alpha = state->state.alpha >> 8, .alpha = state->state.alpha >> 8,
.zpos = state->state.zpos, .zpos = state->state.zpos,
}; };
u32 fourcc = state->format->fourcc;
unsigned int i; unsigned int i;
cfg.src.left = state->state.src.x1 >> 16; cfg.src.left = state->state.src.x1 >> 16;
...@@ -168,9 +169,27 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) ...@@ -168,9 +169,27 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl) cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl)
+ fb->offsets[i]; + fb->offsets[i];
format = rcar_du_format_info(state->format->fourcc); if (state->state.pixel_blend_mode == DRM_MODE_BLEND_PIXEL_NONE) {
switch (fourcc) {
case DRM_FORMAT_ARGB1555:
fourcc = DRM_FORMAT_XRGB1555;
break;
case DRM_FORMAT_ARGB4444:
fourcc = DRM_FORMAT_XRGB4444;
break;
case DRM_FORMAT_ARGB8888:
fourcc = DRM_FORMAT_XRGB8888;
break;
}
}
format = rcar_du_format_info(fourcc);
cfg.pixelformat = format->v4l2; cfg.pixelformat = format->v4l2;
cfg.premult = state->state.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI;
vsp1_du_atomic_update(plane->vsp->vsp, crtc->vsp_pipe, vsp1_du_atomic_update(plane->vsp->vsp, crtc->vsp_pipe,
plane->index, &cfg); plane->index, &cfg);
} }
...@@ -436,6 +455,11 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, ...@@ -436,6 +455,11 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np,
drm_plane_create_zpos_property(&plane->plane, i, 0, drm_plane_create_zpos_property(&plane->plane, i, 0,
num_planes - 1); num_planes - 1);
drm_plane_create_blend_mode_property(&plane->plane,
BIT(DRM_MODE_BLEND_PIXEL_NONE) |
BIT(DRM_MODE_BLEND_PREMULTI) |
BIT(DRM_MODE_BLEND_COVERAGE));
vsp->num_planes++; vsp->num_planes++;
} }
......
...@@ -166,8 +166,8 @@ static int rcar_du_wb_enc_atomic_check(struct drm_encoder *encoder, ...@@ -166,8 +166,8 @@ static int rcar_du_wb_enc_atomic_check(struct drm_encoder *encoder,
wb_state->format = rcar_du_format_info(fb->format->format); wb_state->format = rcar_du_format_info(fb->format->format);
if (wb_state->format == NULL) { if (wb_state->format == NULL) {
dev_dbg(dev->dev, "%s: unsupported format %08x\n", __func__, dev_dbg(dev->dev, "%s: unsupported format %p4cc\n", __func__,
fb->format->format); &fb->format->format);
return -EINVAL; return -EINVAL;
} }
......
...@@ -306,7 +306,7 @@ static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq) ...@@ -306,7 +306,7 @@ static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
* Clock - D3/E3 only * Clock - D3/E3 only
*/ */
int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq) int rcar_lvds_pclk_enable(struct drm_bridge *bridge, unsigned long freq)
{ {
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
int ret; int ret;
...@@ -324,9 +324,9 @@ int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq) ...@@ -324,9 +324,9 @@ int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rcar_lvds_clk_enable); EXPORT_SYMBOL_GPL(rcar_lvds_pclk_enable);
void rcar_lvds_clk_disable(struct drm_bridge *bridge) void rcar_lvds_pclk_disable(struct drm_bridge *bridge)
{ {
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
...@@ -339,7 +339,7 @@ void rcar_lvds_clk_disable(struct drm_bridge *bridge) ...@@ -339,7 +339,7 @@ void rcar_lvds_clk_disable(struct drm_bridge *bridge)
clk_disable_unprepare(lvds->clocks.mod); clk_disable_unprepare(lvds->clocks.mod);
} }
EXPORT_SYMBOL_GPL(rcar_lvds_clk_disable); EXPORT_SYMBOL_GPL(rcar_lvds_pclk_disable);
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Bridge * Bridge
......
...@@ -13,17 +13,17 @@ ...@@ -13,17 +13,17 @@
struct drm_bridge; struct drm_bridge;
#if IS_ENABLED(CONFIG_DRM_RCAR_LVDS) #if IS_ENABLED(CONFIG_DRM_RCAR_LVDS)
int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq); int rcar_lvds_pclk_enable(struct drm_bridge *bridge, unsigned long freq);
void rcar_lvds_clk_disable(struct drm_bridge *bridge); void rcar_lvds_pclk_disable(struct drm_bridge *bridge);
bool rcar_lvds_dual_link(struct drm_bridge *bridge); bool rcar_lvds_dual_link(struct drm_bridge *bridge);
bool rcar_lvds_is_connected(struct drm_bridge *bridge); bool rcar_lvds_is_connected(struct drm_bridge *bridge);
#else #else
static inline int rcar_lvds_clk_enable(struct drm_bridge *bridge, static inline int rcar_lvds_pclk_enable(struct drm_bridge *bridge,
unsigned long freq) unsigned long freq)
{ {
return -ENOSYS; return -ENOSYS;
} }
static inline void rcar_lvds_clk_disable(struct drm_bridge *bridge) { } static inline void rcar_lvds_pclk_disable(struct drm_bridge *bridge) { }
static inline bool rcar_lvds_dual_link(struct drm_bridge *bridge) static inline bool rcar_lvds_dual_link(struct drm_bridge *bridge)
{ {
return false; return false;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include <drm/drm_probe_helper.h> #include <drm/drm_probe_helper.h>
#include "rcar_mipi_dsi.h"
#include "rcar_mipi_dsi_regs.h" #include "rcar_mipi_dsi_regs.h"
struct rcar_mipi_dsi { struct rcar_mipi_dsi {
...@@ -414,7 +415,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, ...@@ -414,7 +415,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi,
/* Enable DOT clock */ /* Enable DOT clock */
vclkset = VCLKSET_CKEN; vclkset = VCLKSET_CKEN;
rcar_mipi_dsi_set(dsi, VCLKSET, vclkset); rcar_mipi_dsi_write(dsi, VCLKSET, vclkset);
if (dsi_format == 24) if (dsi_format == 24)
vclkset |= VCLKSET_BPP_24; vclkset |= VCLKSET_BPP_24;
...@@ -429,7 +430,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, ...@@ -429,7 +430,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi,
vclkset |= VCLKSET_COLOR_RGB | VCLKSET_DIV(setup_info.div) vclkset |= VCLKSET_COLOR_RGB | VCLKSET_DIV(setup_info.div)
| VCLKSET_LANE(dsi->lanes - 1); | VCLKSET_LANE(dsi->lanes - 1);
rcar_mipi_dsi_set(dsi, VCLKSET, vclkset); rcar_mipi_dsi_write(dsi, VCLKSET, vclkset);
/* After setting VCLKSET register, enable VCLKEN */ /* After setting VCLKSET register, enable VCLKEN */
rcar_mipi_dsi_set(dsi, VCLKEN, VCLKEN_CKEN); rcar_mipi_dsi_set(dsi, VCLKEN, VCLKEN_CKEN);
...@@ -441,9 +442,21 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, ...@@ -441,9 +442,21 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi,
static void rcar_mipi_dsi_shutdown(struct rcar_mipi_dsi *dsi) static void rcar_mipi_dsi_shutdown(struct rcar_mipi_dsi *dsi)
{ {
/* Disable VCLKEN */
rcar_mipi_dsi_write(dsi, VCLKSET, 0);
/* Disable DOT clock */
rcar_mipi_dsi_write(dsi, VCLKSET, 0);
rcar_mipi_dsi_clr(dsi, PHYSETUP, PHYSETUP_RSTZ); rcar_mipi_dsi_clr(dsi, PHYSETUP, PHYSETUP_RSTZ);
rcar_mipi_dsi_clr(dsi, PHYSETUP, PHYSETUP_SHUTDOWNZ); rcar_mipi_dsi_clr(dsi, PHYSETUP, PHYSETUP_SHUTDOWNZ);
/* CFGCLK disable */
rcar_mipi_dsi_clr(dsi, CFGCLKSET, CFGCLKSET_CKEN);
/* LPCLK disable */
rcar_mipi_dsi_clr(dsi, LPCLKSET, LPCLKSET_CKEN);
dev_dbg(dsi->dev, "DSI device is shutdown\n"); dev_dbg(dsi->dev, "DSI device is shutdown\n");
} }
...@@ -542,6 +555,34 @@ static int rcar_mipi_dsi_start_video(struct rcar_mipi_dsi *dsi) ...@@ -542,6 +555,34 @@ static int rcar_mipi_dsi_start_video(struct rcar_mipi_dsi *dsi)
return 0; return 0;
} }
static void rcar_mipi_dsi_stop_video(struct rcar_mipi_dsi *dsi)
{
u32 status;
int ret;
/* Disable transmission in video mode. */
rcar_mipi_dsi_clr(dsi, TXVMCR, TXVMCR_EN_VIDEO);
ret = read_poll_timeout(rcar_mipi_dsi_read, status,
!(status & TXVMSR_ACT),
2000, 100000, false, dsi, TXVMSR);
if (ret < 0) {
dev_err(dsi->dev, "Failed to disable video transmission\n");
return;
}
/* Assert video FIFO clear. */
rcar_mipi_dsi_set(dsi, TXVMCR, TXVMCR_VFCLR);
ret = read_poll_timeout(rcar_mipi_dsi_read, status,
!(status & TXVMSR_VFRDY),
2000, 100000, false, dsi, TXVMSR);
if (ret < 0) {
dev_err(dsi->dev, "Failed to assert video FIFO clear\n");
return;
}
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Bridge * Bridge
*/ */
...@@ -558,7 +599,22 @@ static int rcar_mipi_dsi_attach(struct drm_bridge *bridge, ...@@ -558,7 +599,22 @@ static int rcar_mipi_dsi_attach(struct drm_bridge *bridge,
static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge, static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state) struct drm_bridge_state *old_bridge_state)
{ {
struct drm_atomic_state *state = old_bridge_state->base.state; struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge);
rcar_mipi_dsi_start_video(dsi);
}
static void rcar_mipi_dsi_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
{
struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge);
rcar_mipi_dsi_stop_video(dsi);
}
void rcar_mipi_dsi_pclk_enable(struct drm_bridge *bridge,
struct drm_atomic_state *state)
{
struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge); struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge);
const struct drm_display_mode *mode; const struct drm_display_mode *mode;
struct drm_connector *connector; struct drm_connector *connector;
...@@ -586,8 +642,6 @@ static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge, ...@@ -586,8 +642,6 @@ static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
if (ret < 0) if (ret < 0)
goto err_dsi_start_hs; goto err_dsi_start_hs;
rcar_mipi_dsi_start_video(dsi);
return; return;
err_dsi_start_hs: err_dsi_start_hs:
...@@ -595,15 +649,16 @@ static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge, ...@@ -595,15 +649,16 @@ static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
err_dsi_startup: err_dsi_startup:
rcar_mipi_dsi_clk_disable(dsi); rcar_mipi_dsi_clk_disable(dsi);
} }
EXPORT_SYMBOL_GPL(rcar_mipi_dsi_pclk_enable);
static void rcar_mipi_dsi_atomic_disable(struct drm_bridge *bridge, void rcar_mipi_dsi_pclk_disable(struct drm_bridge *bridge)
struct drm_bridge_state *old_bridge_state)
{ {
struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge); struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge);
rcar_mipi_dsi_shutdown(dsi); rcar_mipi_dsi_shutdown(dsi);
rcar_mipi_dsi_clk_disable(dsi); rcar_mipi_dsi_clk_disable(dsi);
} }
EXPORT_SYMBOL_GPL(rcar_mipi_dsi_pclk_disable);
static enum drm_mode_status static enum drm_mode_status
rcar_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, rcar_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* R-Car DSI Encoder
*
* Copyright (C) 2022 Renesas Electronics Corporation
*
* Contact: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
*/
#ifndef __RCAR_MIPI_DSI_H__
#define __RCAR_MIPI_DSI_H__
struct drm_atomic_state;
struct drm_bridge;
#if IS_ENABLED(CONFIG_DRM_RCAR_MIPI_DSI)
void rcar_mipi_dsi_pclk_enable(struct drm_bridge *bridge,
struct drm_atomic_state *state);
void rcar_mipi_dsi_pclk_disable(struct drm_bridge *bridge);
#else
static inline void rcar_mipi_dsi_pclk_enable(struct drm_bridge *bridge,
struct drm_atomic_state *state)
{
}
static inline void rcar_mipi_dsi_pclk_disable(struct drm_bridge *bridge)
{
}
#endif /* CONFIG_DRM_RCAR_MIPI_DSI */
#endif /* __RCAR_MIPI_DSI_H__ */
...@@ -856,6 +856,8 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, ...@@ -856,6 +856,8 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
rpf->mem.addr[1] = cfg->mem[1]; rpf->mem.addr[1] = cfg->mem[1];
rpf->mem.addr[2] = cfg->mem[2]; rpf->mem.addr[2] = cfg->mem[2];
rpf->format.flags = cfg->premult ? V4L2_PIX_FMT_FLAG_PREMUL_ALPHA : 0;
vsp1->drm->inputs[rpf_index].crop = cfg->src; vsp1->drm->inputs[rpf_index].crop = cfg->src;
vsp1->drm->inputs[rpf_index].compose = cfg->dst; vsp1->drm->inputs[rpf_index].compose = cfg->dst;
vsp1->drm->inputs[rpf_index].zpos = cfg->zpos; vsp1->drm->inputs[rpf_index].zpos = cfg->zpos;
......
...@@ -51,6 +51,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index, ...@@ -51,6 +51,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
* @dst: destination rectangle on the display (integer coordinates) * @dst: destination rectangle on the display (integer coordinates)
* @alpha: alpha value (0: fully transparent, 255: fully opaque) * @alpha: alpha value (0: fully transparent, 255: fully opaque)
* @zpos: Z position of the plane (from 0 to number of planes minus 1) * @zpos: Z position of the plane (from 0 to number of planes minus 1)
* @premult: true for premultiplied alpha
*/ */
struct vsp1_du_atomic_config { struct vsp1_du_atomic_config {
u32 pixelformat; u32 pixelformat;
...@@ -60,6 +61,7 @@ struct vsp1_du_atomic_config { ...@@ -60,6 +61,7 @@ struct vsp1_du_atomic_config {
struct v4l2_rect dst; struct v4l2_rect dst;
unsigned int alpha; unsigned int alpha;
unsigned int zpos; unsigned int zpos;
bool premult;
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment