hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/gpu/drm/exynos/exynos_drm_fimd.c
....@@ -1,38 +1,34 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* exynos_drm_fimd.c
23 *
34 * Copyright (C) 2011 Samsung Electronics Co.Ltd
45 * Authors:
56 * Joonyoung Shim <jy0922.shim@samsung.com>
67 * Inki Dae <inki.dae@samsung.com>
7
- *
8
- * This program is free software; you can redistribute it and/or modify it
9
- * under the terms of the GNU General Public License as published by the
10
- * Free Software Foundation; either version 2 of the License, or (at your
11
- * option) any later version.
12
- *
138 */
14
-#include <drm/drmP.h>
159
16
-#include <linux/kernel.h>
17
-#include <linux/platform_device.h>
1810 #include <linux/clk.h>
11
+#include <linux/component.h>
12
+#include <linux/kernel.h>
13
+#include <linux/mfd/syscon.h>
1914 #include <linux/of.h>
2015 #include <linux/of_device.h>
16
+#include <linux/platform_device.h>
2117 #include <linux/pm_runtime.h>
22
-#include <linux/component.h>
23
-#include <linux/mfd/syscon.h>
2418 #include <linux/regmap.h>
2519
2620 #include <video/of_display_timing.h>
2721 #include <video/of_videomode.h>
2822 #include <video/samsung_fimd.h>
23
+
24
+#include <drm/drm_fourcc.h>
25
+#include <drm/drm_vblank.h>
2926 #include <drm/exynos_drm.h>
3027
28
+#include "exynos_drm_crtc.h"
3129 #include "exynos_drm_drv.h"
3230 #include "exynos_drm_fb.h"
33
-#include "exynos_drm_crtc.h"
3431 #include "exynos_drm_plane.h"
35
-#include "exynos_drm_iommu.h"
3632
3733 /*
3834 * FIMD stands for Fully Interactive Mobile Display and
....@@ -171,6 +167,7 @@
171167 struct fimd_context {
172168 struct device *dev;
173169 struct drm_device *drm_dev;
170
+ void *dma_priv;
174171 struct exynos_drm_crtc *crtc;
175172 struct exynos_drm_plane planes[WINDOWS_NR];
176173 struct exynos_drm_plane_config configs[WINDOWS_NR];
....@@ -228,6 +225,21 @@
228225 DRM_FORMAT_XRGB8888,
229226 DRM_FORMAT_ARGB8888,
230227 };
228
+
229
+static const unsigned int capabilities[WINDOWS_NR] = {
230
+ 0,
231
+ EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
232
+ EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
233
+ EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
234
+ EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND,
235
+};
236
+
237
+static inline void fimd_set_bits(struct fimd_context *ctx, u32 reg, u32 mask,
238
+ u32 val)
239
+{
240
+ val = (val & mask) | (readl(ctx->regs + reg) & ~mask);
241
+ writel(val, ctx->regs + reg);
242
+}
231243
232244 static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
233245 {
....@@ -301,7 +313,7 @@
301313 if (!wait_event_timeout(ctx->wait_vsync_queue,
302314 !atomic_read(&ctx->wait_vsync_event),
303315 HZ/20))
304
- DRM_DEBUG_KMS("vblank wait timed out.\n");
316
+ DRM_DEV_DEBUG_KMS(ctx->dev, "vblank wait timed out.\n");
305317 }
306318
307319 static void fimd_enable_video_output(struct fimd_context *ctx, unsigned int win,
....@@ -335,8 +347,6 @@
335347 {
336348 struct fimd_context *ctx = crtc->ctx;
337349 unsigned int win, ch_enabled = 0;
338
-
339
- DRM_DEBUG_KMS("%s\n", __FILE__);
340350
341351 /* Hardware is in unknown state, so ensure it gets enabled properly */
342352 pm_runtime_get_sync(ctx->dev);
....@@ -386,7 +396,7 @@
386396 u32 clkdiv;
387397
388398 if (mode->clock == 0) {
389
- DRM_INFO("Mode has zero clock value.\n");
399
+ DRM_DEV_ERROR(ctx->dev, "Mode has zero clock value.\n");
390400 return -EINVAL;
391401 }
392402
....@@ -402,15 +412,17 @@
402412
403413 lcd_rate = clk_get_rate(ctx->lcd_clk);
404414 if (2 * lcd_rate < ideal_clk) {
405
- DRM_INFO("sclk_fimd clock too low(%lu) for requested pixel clock(%lu)\n",
406
- lcd_rate, ideal_clk);
415
+ DRM_DEV_ERROR(ctx->dev,
416
+ "sclk_fimd clock too low(%lu) for requested pixel clock(%lu)\n",
417
+ lcd_rate, ideal_clk);
407418 return -EINVAL;
408419 }
409420
410421 /* Find the clock divider value that gets us closest to ideal_clk */
411422 clkdiv = DIV_ROUND_CLOSEST(lcd_rate, ideal_clk);
412423 if (clkdiv >= 0x200) {
413
- DRM_INFO("requested pixel clock(%lu) too low\n", ideal_clk);
424
+ DRM_DEV_ERROR(ctx->dev, "requested pixel clock(%lu) too low\n",
425
+ ideal_clk);
414426 return -EINVAL;
415427 }
416428
....@@ -467,7 +479,8 @@
467479 driver_data->lcdblk_offset,
468480 0x3 << driver_data->lcdblk_vt_shift,
469481 0x1 << driver_data->lcdblk_vt_shift)) {
470
- DRM_ERROR("Failed to update sysreg for I80 i/f.\n");
482
+ DRM_DEV_ERROR(ctx->dev,
483
+ "Failed to update sysreg for I80 i/f.\n");
471484 return;
472485 }
473486 } else {
....@@ -511,7 +524,8 @@
511524 driver_data->lcdblk_offset,
512525 0x1 << driver_data->lcdblk_bypass_shift,
513526 0x1 << driver_data->lcdblk_bypass_shift)) {
514
- DRM_ERROR("Failed to update sysreg for bypass setting.\n");
527
+ DRM_DEV_ERROR(ctx->dev,
528
+ "Failed to update sysreg for bypass setting.\n");
515529 return;
516530 }
517531
....@@ -523,7 +537,8 @@
523537 driver_data->lcdblk_offset,
524538 0x1 << driver_data->lcdblk_mic_bypass_shift,
525539 0x1 << driver_data->lcdblk_mic_bypass_shift)) {
526
- DRM_ERROR("Failed to update sysreg for bypass mic.\n");
540
+ DRM_DEV_ERROR(ctx->dev,
541
+ "Failed to update sysreg for bypass mic.\n");
527542 return;
528543 }
529544
....@@ -552,13 +567,88 @@
552567 writel(val, ctx->regs + VIDCON0);
553568 }
554569
570
+static void fimd_win_set_bldeq(struct fimd_context *ctx, unsigned int win,
571
+ unsigned int alpha, unsigned int pixel_alpha)
572
+{
573
+ u32 mask = BLENDEQ_A_FUNC_F(0xf) | BLENDEQ_B_FUNC_F(0xf);
574
+ u32 val = 0;
575
+
576
+ switch (pixel_alpha) {
577
+ case DRM_MODE_BLEND_PIXEL_NONE:
578
+ case DRM_MODE_BLEND_COVERAGE:
579
+ val |= BLENDEQ_A_FUNC_F(BLENDEQ_ALPHA_A);
580
+ val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A);
581
+ break;
582
+ case DRM_MODE_BLEND_PREMULTI:
583
+ default:
584
+ if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
585
+ val |= BLENDEQ_A_FUNC_F(BLENDEQ_ALPHA0);
586
+ val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A);
587
+ } else {
588
+ val |= BLENDEQ_A_FUNC_F(BLENDEQ_ONE);
589
+ val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A);
590
+ }
591
+ break;
592
+ }
593
+ fimd_set_bits(ctx, BLENDEQx(win), mask, val);
594
+}
595
+
596
+static void fimd_win_set_bldmod(struct fimd_context *ctx, unsigned int win,
597
+ unsigned int alpha, unsigned int pixel_alpha)
598
+{
599
+ u32 win_alpha_l = (alpha >> 8) & 0xf;
600
+ u32 win_alpha_h = alpha >> 12;
601
+ u32 val = 0;
602
+
603
+ switch (pixel_alpha) {
604
+ case DRM_MODE_BLEND_PIXEL_NONE:
605
+ break;
606
+ case DRM_MODE_BLEND_COVERAGE:
607
+ case DRM_MODE_BLEND_PREMULTI:
608
+ default:
609
+ val |= WINCON1_ALPHA_SEL;
610
+ val |= WINCON1_BLD_PIX;
611
+ val |= WINCON1_ALPHA_MUL;
612
+ break;
613
+ }
614
+ fimd_set_bits(ctx, WINCON(win), WINCONx_BLEND_MODE_MASK, val);
615
+
616
+ /* OSD alpha */
617
+ val = VIDISD14C_ALPHA0_R(win_alpha_h) |
618
+ VIDISD14C_ALPHA0_G(win_alpha_h) |
619
+ VIDISD14C_ALPHA0_B(win_alpha_h) |
620
+ VIDISD14C_ALPHA1_R(0x0) |
621
+ VIDISD14C_ALPHA1_G(0x0) |
622
+ VIDISD14C_ALPHA1_B(0x0);
623
+ writel(val, ctx->regs + VIDOSD_C(win));
624
+
625
+ val = VIDW_ALPHA_R(win_alpha_l) | VIDW_ALPHA_G(win_alpha_l) |
626
+ VIDW_ALPHA_B(win_alpha_l);
627
+ writel(val, ctx->regs + VIDWnALPHA0(win));
628
+
629
+ val = VIDW_ALPHA_R(0x0) | VIDW_ALPHA_G(0x0) |
630
+ VIDW_ALPHA_B(0x0);
631
+ writel(val, ctx->regs + VIDWnALPHA1(win));
632
+
633
+ fimd_set_bits(ctx, BLENDCON, BLENDCON_NEW_MASK,
634
+ BLENDCON_NEW_8BIT_ALPHA_VALUE);
635
+}
555636
556637 static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
557
- uint32_t pixel_format, int width)
638
+ struct drm_framebuffer *fb, int width)
558639 {
559
- unsigned long val;
640
+ struct exynos_drm_plane plane = ctx->planes[win];
641
+ struct exynos_drm_plane_state *state =
642
+ to_exynos_plane_state(plane.base.state);
643
+ uint32_t pixel_format = fb->format->format;
644
+ unsigned int alpha = state->base.alpha;
645
+ u32 val = WINCONx_ENWIN;
646
+ unsigned int pixel_alpha;
560647
561
- val = WINCONx_ENWIN;
648
+ if (fb->format->has_alpha)
649
+ pixel_alpha = state->base.pixel_blend_mode;
650
+ else
651
+ pixel_alpha = DRM_MODE_BLEND_PIXEL_NONE;
562652
563653 /*
564654 * In case of s3c64xx, window 0 doesn't support alpha channel.
....@@ -592,8 +682,7 @@
592682 break;
593683 case DRM_FORMAT_ARGB8888:
594684 default:
595
- val |= WINCON1_BPPMODE_25BPP_A1888
596
- | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
685
+ val |= WINCON1_BPPMODE_25BPP_A1888;
597686 val |= WINCONx_WSWP;
598687 val |= WINCONx_BURSTLEN_16WORD;
599688 break;
....@@ -611,25 +700,12 @@
611700 val &= ~WINCONx_BURSTLEN_MASK;
612701 val |= WINCONx_BURSTLEN_4WORD;
613702 }
614
-
615
- writel(val, ctx->regs + WINCON(win));
703
+ fimd_set_bits(ctx, WINCON(win), ~WINCONx_BLEND_MODE_MASK, val);
616704
617705 /* hardware window 0 doesn't support alpha channel. */
618706 if (win != 0) {
619
- /* OSD alpha */
620
- val = VIDISD14C_ALPHA0_R(0xf) |
621
- VIDISD14C_ALPHA0_G(0xf) |
622
- VIDISD14C_ALPHA0_B(0xf) |
623
- VIDISD14C_ALPHA1_R(0xf) |
624
- VIDISD14C_ALPHA1_G(0xf) |
625
- VIDISD14C_ALPHA1_B(0xf);
626
-
627
- writel(val, ctx->regs + VIDOSD_C(win));
628
-
629
- val = VIDW_ALPHA_R(0xf) | VIDW_ALPHA_G(0xf) |
630
- VIDW_ALPHA_G(0xf);
631
- writel(val, ctx->regs + VIDWnALPHA0(win));
632
- writel(val, ctx->regs + VIDWnALPHA1(win));
707
+ fimd_win_set_bldmod(ctx, win, alpha, pixel_alpha);
708
+ fimd_win_set_bldeq(ctx, win, alpha, pixel_alpha);
633709 }
634710 }
635711
....@@ -739,10 +815,11 @@
739815 val = (unsigned long)(dma_addr + size);
740816 writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
741817
742
- DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
743
- (unsigned long)dma_addr, val, size);
744
- DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
745
- state->crtc.w, state->crtc.h);
818
+ DRM_DEV_DEBUG_KMS(ctx->dev,
819
+ "start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
820
+ (unsigned long)dma_addr, val, size);
821
+ DRM_DEV_DEBUG_KMS(ctx->dev, "ovl_width = %d, ovl_height = %d\n",
822
+ state->crtc.w, state->crtc.h);
746823
747824 /* buffer size */
748825 buf_offsize = pitch - (state->crtc.w * cpp);
....@@ -772,8 +849,9 @@
772849
773850 writel(val, ctx->regs + VIDOSD_B(win));
774851
775
- DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
776
- state->crtc.x, state->crtc.y, last_x, last_y);
852
+ DRM_DEV_DEBUG_KMS(ctx->dev,
853
+ "osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
854
+ state->crtc.x, state->crtc.y, last_x, last_y);
777855
778856 /* OSD size */
779857 if (win != 3 && win != 4) {
....@@ -783,10 +861,11 @@
783861 val = state->crtc.w * state->crtc.h;
784862 writel(val, ctx->regs + offset);
785863
786
- DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
864
+ DRM_DEV_DEBUG_KMS(ctx->dev, "osd size = 0x%x\n",
865
+ (unsigned int)val);
787866 }
788867
789
- fimd_win_set_pixfmt(ctx, win, fb->format->format, state->src.w);
868
+ fimd_win_set_pixfmt(ctx, win, fb, state->src.w);
790869
791870 /* hardware window 0 doesn't support color key. */
792871 if (win != 0)
....@@ -816,7 +895,7 @@
816895 fimd_enable_shadow_channel_path(ctx, win, false);
817896 }
818897
819
-static void fimd_enable(struct exynos_drm_crtc *crtc)
898
+static void fimd_atomic_enable(struct exynos_drm_crtc *crtc)
820899 {
821900 struct fimd_context *ctx = crtc->ctx;
822901
....@@ -834,7 +913,7 @@
834913 fimd_commit(ctx->crtc);
835914 }
836915
837
-static void fimd_disable(struct exynos_drm_crtc *crtc)
916
+static void fimd_atomic_disable(struct exynos_drm_crtc *crtc)
838917 {
839918 struct fimd_context *ctx = crtc->ctx;
840919 int i;
....@@ -928,8 +1007,8 @@
9281007 }
9291008
9301009 static const struct exynos_drm_crtc_ops fimd_crtc_ops = {
931
- .enable = fimd_enable,
932
- .disable = fimd_disable,
1010
+ .atomic_enable = fimd_atomic_enable,
1011
+ .atomic_disable = fimd_atomic_disable,
9331012 .enable_vblank = fimd_enable_vblank,
9341013 .disable_vblank = fimd_disable_vblank,
9351014 .atomic_begin = fimd_atomic_begin,
....@@ -988,6 +1067,7 @@
9881067 ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats);
9891068 ctx->configs[i].zpos = i;
9901069 ctx->configs[i].type = fimd_win_types[i];
1070
+ ctx->configs[i].capabilities = capabilities[i];
9911071 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
9921072 &ctx->configs[i]);
9931073 if (ret)
....@@ -1011,7 +1091,7 @@
10111091 if (is_drm_iommu_supported(drm_dev))
10121092 fimd_clear_channels(ctx->crtc);
10131093
1014
- return drm_iommu_attach_device(drm_dev, dev);
1094
+ return exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
10151095 }
10161096
10171097 static void fimd_unbind(struct device *dev, struct device *master,
....@@ -1019,9 +1099,9 @@
10191099 {
10201100 struct fimd_context *ctx = dev_get_drvdata(dev);
10211101
1022
- fimd_disable(ctx->crtc);
1102
+ fimd_atomic_disable(ctx->crtc);
10231103
1024
- drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
1104
+ exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv);
10251105
10261106 if (ctx->encoder)
10271107 exynos_dpi_remove(ctx->encoder);
....@@ -1176,13 +1256,17 @@
11761256
11771257 ret = clk_prepare_enable(ctx->bus_clk);
11781258 if (ret < 0) {
1179
- DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
1259
+ DRM_DEV_ERROR(dev,
1260
+ "Failed to prepare_enable the bus clk [%d]\n",
1261
+ ret);
11801262 return ret;
11811263 }
11821264
11831265 ret = clk_prepare_enable(ctx->lcd_clk);
11841266 if (ret < 0) {
1185
- DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n", ret);
1267
+ DRM_DEV_ERROR(dev,
1268
+ "Failed to prepare_enable the lcd clk [%d]\n",
1269
+ ret);
11861270 return ret;
11871271 }
11881272