diff options
Diffstat (limited to 'drivers/gpu/drm/rcar-du')
-rw-r--r-- | drivers/gpu/drm/rcar-du/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/Makefile | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 34 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_drv.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_kms.c | 41 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_plane.c | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_writeback.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_lvds.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_lvds.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 69 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h | 31 |
14 files changed, 212 insertions, 81 deletions
diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index f6e6a6d5d987..c959e8c6be7d 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -5,7 +5,7 @@ config DRM_RCAR_DU depends on ARM || ARM64 depends on ARCH_RENESAS || COMPILE_TEST select DRM_KMS_HELPER - select DRM_GEM_CMA_HELPER + select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS help Choose this option if you have an R-Car chipset. diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile index e7275b5e7ec8..6f132325c8b7 100644 --- a/drivers/gpu/drm/rcar-du/Makefile +++ b/drivers/gpu/drm/rcar-du/Makefile @@ -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_LVDS) += rcar_lvds.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 diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 621bbccb95d4..3619e1ddeb62 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -17,9 +17,7 @@ #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> -#include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_vblank.h> #include "rcar_cmm.h" @@ -31,6 +29,7 @@ #include "rcar_du_regs.h" #include "rcar_du_vsp.h" #include "rcar_lvds.h" +#include "rcar_mipi_dsi.h" static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg) { @@ -746,7 +745,19 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, const struct drm_display_mode *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); @@ -779,7 +790,20 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, * Disable the LVDS clock output, see * 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); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 70d85610d720..a2776f1d6f2c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -20,15 +20,13 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> #include "rcar_du_drv.h" #include "rcar_du_kms.h" -#include "rcar_du_regs.h" /* ----------------------------------------------------------------------------- * Device Information @@ -508,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 = { .gen = 3, .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), .routes = { /* R8A779A0 has two MIPI DSI outputs. */ @@ -579,7 +578,7 @@ const char *rcar_du_output_name(enum rcar_du_output output) * DRM operations */ -DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops); +DEFINE_DRM_GEM_DMA_FOPS(rcar_du_fops); static const struct drm_driver rcar_du_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index bfad7775d9a1..5cfa2bb7ad93 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -31,6 +31,7 @@ struct rcar_du_device; #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_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 */ @@ -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_VSPS 4 #define RCAR_DU_MAX_LVDS 2 +#define RCAR_DU_MAX_DSI 2 struct rcar_du_device { struct device *dev; @@ -107,6 +109,7 @@ struct rcar_du_device { struct platform_device *cmms[RCAR_DU_MAX_CRTCS]; struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS]; struct drm_bridge *lvds[RCAR_DU_MAX_LVDS]; + struct drm_bridge *dsi[RCAR_DU_MAX_DSI]; struct { struct drm_property *colorkey; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 60d6be78323b..b1787be31e92 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -9,18 +9,13 @@ #include <linux/export.h> #include <linux/of.h> -#include <linux/slab.h> #include <drm/drm_bridge.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 "rcar_du_drv.h" #include "rcar_du_encoder.h" -#include "rcar_du_kms.h" #include "rcar_lvds.h" /* ----------------------------------------------------------------------------- @@ -84,6 +79,10 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, if (output == RCAR_DU_OUTPUT_LVDS0 || output == RCAR_DU_OUTPUT_LVDS1) 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; } /* diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 761451ee5263..8c2719efda2a 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -11,9 +11,8 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> @@ -328,12 +327,12 @@ const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc) */ static const struct drm_gem_object_funcs rcar_du_gem_funcs = { - .free = drm_gem_cma_object_free, - .print_info = drm_gem_cma_object_print_info, - .get_sg_table = drm_gem_cma_object_get_sg_table, - .vmap = drm_gem_cma_object_vmap, - .mmap = drm_gem_cma_object_mmap, - .vm_ops = &drm_gem_cma_vm_ops, + .free = drm_gem_dma_object_free, + .print_info = drm_gem_dma_object_print_info, + .get_sg_table = drm_gem_dma_object_get_sg_table, + .vmap = drm_gem_dma_object_vmap, + .mmap = drm_gem_dma_object_mmap, + .vm_ops = &drm_gem_dma_vm_ops, }; struct drm_gem_object *rcar_du_gem_prime_import_sg_table(struct drm_device *dev, @@ -341,33 +340,33 @@ struct drm_gem_object *rcar_du_gem_prime_import_sg_table(struct drm_device *dev, struct sg_table *sgt) { struct rcar_du_device *rcdu = to_rcar_du_device(dev); - struct drm_gem_cma_object *cma_obj; + struct drm_gem_dma_object *dma_obj; struct drm_gem_object *gem_obj; int ret; if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) - return drm_gem_cma_prime_import_sg_table(dev, attach, sgt); + return drm_gem_dma_prime_import_sg_table(dev, attach, sgt); - /* Create a CMA GEM buffer. */ - cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); - if (!cma_obj) + /* Create a DMA GEM buffer. */ + dma_obj = kzalloc(sizeof(*dma_obj), GFP_KERNEL); + if (!dma_obj) return ERR_PTR(-ENOMEM); - gem_obj = &cma_obj->base; + gem_obj = &dma_obj->base; gem_obj->funcs = &rcar_du_gem_funcs; drm_gem_private_object_init(dev, gem_obj, attach->dmabuf->size); - cma_obj->map_noncoherent = false; + dma_obj->map_noncoherent = false; ret = drm_gem_create_mmap_offset(gem_obj); if (ret) { drm_gem_object_release(gem_obj); - kfree(cma_obj); + kfree(dma_obj); return ERR_PTR(ret); } - cma_obj->paddr = 0; - cma_obj->sgt = sgt; + dma_obj->dma_addr = 0; + dma_obj->sgt = sgt; return gem_obj; } @@ -390,7 +389,7 @@ int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev, args->pitch = roundup(min_pitch, align); - return drm_gem_cma_dumb_create_internal(file, dev, args); + return drm_gem_dma_dumb_create_internal(file, dev, args); } static struct drm_framebuffer * @@ -406,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); if (format == NULL) { - dev_dbg(dev->dev, "unsupported pixel format %08x\n", - mode_cmd->pixel_format); + dev_dbg(dev->dev, "unsupported pixel format %p4cc\n", + &mode_cmd->pixel_format); return ERR_PTR(-EINVAL); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 501d79367e3e..d759e0192181 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -12,11 +12,10 @@ #include <drm/drm_blend.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> -#include <drm/drm_gem_cma_helper.h> -#include <drm/drm_plane_helper.h> +#include <drm/drm_gem_dma_helper.h> #include "rcar_du_drv.h" #include "rcar_du_group.h" @@ -342,7 +341,7 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp, if (state->source == RCAR_DU_PLANE_MEMORY) { struct drm_framebuffer *fb = state->state.fb; - struct drm_gem_cma_object *gem; + struct drm_gem_dma_object *gem; unsigned int i; if (state->format->planes == 2) @@ -351,8 +350,8 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp, pitch = fb->pitches[0] * 8 / state->format->bpp; for (i = 0; i < state->format->planes; ++i) { - gem = drm_fb_cma_get_gem_obj(fb, i); - dma[i] = gem->paddr + fb->offsets[i]; + gem = drm_fb_dma_get_gem_obj(fb, i); + dma[i] = gem->dma_addr + fb->offsets[i]; } } else { pitch = drm_rect_width(&state->state.src) >> 16; @@ -507,8 +506,15 @@ static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp, unsigned int index, const struct rcar_du_plane_state *state) { - rcar_du_plane_write(rgrp, index, PnMR, - PnMR_SPIM_TP_OFF | state->format->pnmr); + struct rcar_du_device *rcdu = rgrp->dev; + 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, state->format->edf | PnDDCR4_CODE); @@ -522,7 +528,6 @@ static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp, * register to 0 to avoid this. */ - /* TODO: Check if alpha-blending should be disabled in PnMR. */ rcar_du_plane_write(rgrp, index, PnALPHAR, 0); } @@ -607,8 +612,8 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane, return PTR_ERR(crtc_state); ret = drm_atomic_helper_check_plane_state(state, crtc_state, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, true, true); if (ret < 0) return ret; @@ -620,8 +625,8 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane, *format = rcar_du_format_info(state->fb->format->format); if (*format == NULL) { - dev_dbg(dev->dev, "%s: unsupported format %08x\n", __func__, - state->fb->format->format); + dev_dbg(dev->dev, "%s: unsupported format %p4cc\n", __func__, + &state->fb->format->format); return -EINVAL; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index dbc68cdabcff..e465aef41585 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -11,13 +11,12 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> #include <drm/drm_crtc.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_dma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_dma_helper.h> #include <drm/drm_managed.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include <linux/bitops.h> @@ -153,6 +152,7 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) .alpha = state->state.alpha >> 8, .zpos = state->state.zpos, }; + u32 fourcc = state->format->fourcc; unsigned int i; cfg.src.left = state->state.src.x1 >> 16; @@ -169,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) + 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.premult = state->state.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI; + vsp1_du_atomic_update(plane->vsp->vsp, crtc->vsp_pipe, plane->index, &cfg); } @@ -184,7 +202,7 @@ int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb, int ret; for (i = 0; i < fb->format->num_planes; ++i) { - struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i); + struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i); struct sg_table *sgt = &sg_tables[i]; if (gem->sgt) { @@ -213,7 +231,7 @@ int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb, } } else { ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, - gem->paddr, gem->base.size); + gem->dma_addr, gem->base.size); if (ret) goto fail; } @@ -437,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, 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++; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c b/drivers/gpu/drm/rcar-du/rcar_du_writeback.c index 25f50a297c11..8cd37d7b8ae2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_writeback.c @@ -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); if (wb_state->format == NULL) { - dev_dbg(dev->dev, "%s: unsupported format %08x\n", __func__, - fb->format->format); + dev_dbg(dev->dev, "%s: unsupported format %p4cc\n", __func__, + &fb->format->format); return -EINVAL; } diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index d85aa4bc7f84..81a060c2fe3f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -306,7 +306,7 @@ static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq) * 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); int ret; @@ -324,9 +324,9 @@ int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq) 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); @@ -339,7 +339,7 @@ void rcar_lvds_clk_disable(struct drm_bridge *bridge) clk_disable_unprepare(lvds->clocks.mod); } -EXPORT_SYMBOL_GPL(rcar_lvds_clk_disable); +EXPORT_SYMBOL_GPL(rcar_lvds_pclk_disable); /* ----------------------------------------------------------------------------- * Bridge diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.h b/drivers/gpu/drm/rcar-du/rcar_lvds.h index 3097bf749bec..bee7033b60d6 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.h +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.h @@ -13,17 +13,17 @@ struct drm_bridge; #if IS_ENABLED(CONFIG_DRM_RCAR_LVDS) -int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq); -void rcar_lvds_clk_disable(struct drm_bridge *bridge); +int rcar_lvds_pclk_enable(struct drm_bridge *bridge, unsigned long freq); +void rcar_lvds_pclk_disable(struct drm_bridge *bridge); bool rcar_lvds_dual_link(struct drm_bridge *bridge); bool rcar_lvds_is_connected(struct drm_bridge *bridge); #else -static inline int rcar_lvds_clk_enable(struct drm_bridge *bridge, - unsigned long freq) +static inline int rcar_lvds_pclk_enable(struct drm_bridge *bridge, + unsigned long freq) { 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) { return false; diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c index 62f7eb84ab01..a7f2b7f66a17 100644 --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c @@ -25,6 +25,7 @@ #include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> +#include "rcar_mipi_dsi.h" #include "rcar_mipi_dsi_regs.h" struct rcar_mipi_dsi { @@ -414,7 +415,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, /* Enable DOT clock */ vclkset = VCLKSET_CKEN; - rcar_mipi_dsi_set(dsi, VCLKSET, vclkset); + rcar_mipi_dsi_write(dsi, VCLKSET, vclkset); if (dsi_format == 24) vclkset |= VCLKSET_BPP_24; @@ -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_LANE(dsi->lanes - 1); - rcar_mipi_dsi_set(dsi, VCLKSET, vclkset); + rcar_mipi_dsi_write(dsi, VCLKSET, vclkset); /* After setting VCLKSET register, enable VCLKEN */ rcar_mipi_dsi_set(dsi, VCLKEN, VCLKEN_CKEN); @@ -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) { + /* 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_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"); } @@ -542,6 +555,34 @@ static int rcar_mipi_dsi_start_video(struct rcar_mipi_dsi *dsi) 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 */ @@ -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, 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); const struct drm_display_mode *mode; struct drm_connector *connector; @@ -586,8 +642,6 @@ static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge, if (ret < 0) goto err_dsi_start_hs; - rcar_mipi_dsi_start_video(dsi); - return; err_dsi_start_hs: @@ -595,15 +649,16 @@ err_dsi_start_hs: err_dsi_startup: 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, - struct drm_bridge_state *old_bridge_state) +void rcar_mipi_dsi_pclk_disable(struct drm_bridge *bridge) { struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge); rcar_mipi_dsi_shutdown(dsi); rcar_mipi_dsi_clk_disable(dsi); } +EXPORT_SYMBOL_GPL(rcar_mipi_dsi_pclk_disable); static enum drm_mode_status rcar_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h new file mode 100644 index 000000000000..528a196e6edd --- /dev/null +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.h @@ -0,0 +1,31 @@ +/* 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__ */ |