History

Merge tag 'shmob-drm-atomic-dt-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers into drm-next

drm: renesas: shmobile: Atomic conversion + DT support Currently, there are two drivers for the LCD controller on Renesas SuperH-based and ARM-based SH-Mobile and R-Mobile SoCs: 1. sh_mobile_lcdcfb, using the fbdev framework, 2. shmob_drm, using the DRM framework. However, only the former driver is used, as all platform support integrates the former. None of these drivers support DT-based systems. Convert the SH-Mobile DRM driver to atomic modesetting, and add DT support, complemented by the customary set of fixes and improvements. Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://lore.kernel.org/r/cover.1694767208.git.geert+renesas@glider.be/ Signed-off-by: Dave Airlie <airlied@redhat.com>

Dave Airlie committed 3 years ago

Commit 2ba446f2 parents 6318080 1399eba17 files · +860 −813Browse files

Unified · Split

17 files
  1. Documentation/devicetree/bindings/display/renesas,shmobile-lcdc.yaml +130 −0
  2. Documentation/userspace-api/media/v4l/subdev-formats.rst +72 −0
  3. MAINTAINERS +11 −2
  4. drivers/gpu/drm/renesas/shmobile/Kconfig +2 −1
  5. drivers/gpu/drm/renesas/shmobile/Makefile +1 −2
  6. drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.c +0 −82
  7. drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.h +0 −19
  8. drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c +280 −370
  9. drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.h +9 −18
  10. drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c +83 −96
  11. drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.h +14 −4
  12. drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.c +55 −22
  13. drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.h +6 −3
  14. drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.c +189 −137
  15. drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.h +3 −2
  16. include/linux/platform_data/shmob_drm.h +3 −54
  17. include/uapi/linux/media-bus-format.h +2 −1
Documentation/devicetree/bindings/display/renesas,shmobile-lcdc.yaml+130−0
@@ -0,0 +1,130 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/display/renesas,shmobile-lcdc.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Renesas SH-Mobile LCD Controller (LCDC)
8
9maintainers:
10 - Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
11 - Geert Uytterhoeven <geert+renesas@glider.be>
12
13properties:
14 compatible:
15 enum:
16 - renesas,r8a7740-lcdc # R-Mobile A1
17 - renesas,sh73a0-lcdc # SH-Mobile AG5
18
19 reg:
20 maxItems: 1
21
22 interrupts:
23 maxItems: 1
24
25 clocks:
26 minItems: 1
27 maxItems: 5
28 description:
29 Only the functional clock is mandatory.
30 Some of the optional clocks are model-dependent (e.g. "video" (a.k.a.
31 "vou" or "dv_clk") is available on R-Mobile A1 only).
32
33 clock-names:
34 minItems: 1
35 items:
36 - const: fck
37 - enum: [ media, lclk, hdmi, video ]
38 - enum: [ media, lclk, hdmi, video ]
39 - enum: [ media, lclk, hdmi, video ]
40 - enum: [ media, lclk, hdmi, video ]
41
42 power-domains:
43 maxItems: 1
44
45 ports:
46 $ref: /schemas/graph.yaml#/properties/ports
47
48 properties:
49 port@0:
50 $ref: /schemas/graph.yaml#/properties/port
51 description: LCD port (R-Mobile A1 and SH-Mobile AG5)
52 unevaluatedProperties: false
53
54 port@1:
55 $ref: /schemas/graph.yaml#/properties/port
56 description: HDMI port (R-Mobile A1 LCDC1 and SH-Mobile AG5)
57 unevaluatedProperties: false
58
59 port@2:
60 $ref: /schemas/graph.yaml#/properties/port
61 description: MIPI-DSI port (SH-Mobile AG5)
62 unevaluatedProperties: false
63
64 required:
65 - port@0
66
67 unevaluatedProperties: false
68
69required:
70 - compatible
71 - reg
72 - interrupts
73 - clocks
74 - clock-names
75 - power-domains
76 - ports
77
78additionalProperties: false
79
80allOf:
81 - if:
82 properties:
83 compatible:
84 contains:
85 const: renesas,r8a7740-lcdc
86 then:
87 properties:
88 ports:
89 properties:
90 port@2: false
91
92 - if:
93 properties:
94 compatible:
95 contains:
96 const: renesas,sh73a0-lcdc
97 then:
98 properties:
99 ports:
100 required:
101 - port@1
102 - port@2
103
104examples:
105 - |
106 #include <dt-bindings/clock/r8a7740-clock.h>
107 #include <dt-bindings/interrupt-controller/arm-gic.h>
108
109 lcd-controller@fe940000 {
110 compatible = "renesas,r8a7740-lcdc";
111 reg = <0xfe940000 0x4000>;
112 interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
113 clocks = <&mstp1_clks R8A7740_CLK_LCDC0>,
114 <&cpg_clocks R8A7740_CLK_M3>, <&lcdlclk0_clk>,
115 <&vou_clk>;
116 clock-names = "fck", "media", "lclk", "video";
117 power-domains = <&pd_a4lc>;
118
119 ports {
120 #address-cells = <1>;
121 #size-cells = <0>;
122
123 port@0 {
124 reg = <0>;
125
126 lcdc0_rgb: endpoint {
127 };
128 };
129 };
130 };
Documentation/userspace-api/media/v4l/subdev-formats.rst+72−0
@@ -949,6 +949,78 @@ The following tables list existing packed RGB formats. · 948 unmodified lines
949 - b\ :sub:`2`949 - b\ :sub:`2`
950 - b\ :sub:`1`950 - b\ :sub:`1`
951 - b\ :sub:`0`951 - b\ :sub:`0`
952 * .. _MEDIA-BUS-FMT-RGB666-2X9-BE:
953
954 - MEDIA_BUS_FMT_RGB666_2X9_BE
955 - 0x1025
956 -
957 -
958 -
959 -
960 -
961 -
962 -
963 -
964 -
965 -
966 -
967 -
968 -
969 -
970 -
971 -
972 -
973 -
974 -
975 -
976 -
977 -
978 -
979 -
980 - r\ :sub:`5`
981 - r\ :sub:`4`
982 - r\ :sub:`3`
983 - r\ :sub:`2`
984 - r\ :sub:`1`
985 - r\ :sub:`0`
986 - g\ :sub:`5`
987 - g\ :sub:`4`
988 - g\ :sub:`3`
989 * -
990 -
991 -
992 -
993 -
994 -
995 -
996 -
997 -
998 -
999 -
1000 -
1001 -
1002 -
1003 -
1004 -
1005 -
1006 -
1007 -
1008 -
1009 -
1010 -
1011 -
1012 -
1013 -
1014 -
1015 - g\ :sub:`2`
1016 - g\ :sub:`1`
1017 - g\ :sub:`0`
1018 - b\ :sub:`5`
1019 - b\ :sub:`4`
1020 - b\ :sub:`3`
1021 - b\ :sub:`2`
1022 - b\ :sub:`1`
1023 - b\ :sub:`0`
952 * .. _MEDIA-BUS-FMT-BGR666-1X18:1024 * .. _MEDIA-BUS-FMT-BGR666-1X18:
953 1025
954 - MEDIA_BUS_FMT_BGR666_1X181026 - MEDIA_BUS_FMT_BGR666_1X18
MAINTAINERS+11−2
@@ -7053,7 +7053,7 @@ F: drivers/gpu/host1x/ · 7052 unmodified lines
7053F: include/linux/host1x.h7053F: include/linux/host1x.h
7054F: include/uapi/drm/tegra_drm.h7054F: include/uapi/drm/tegra_drm.h
7055 7055
7056DRM DRIVERS FOR RENESAS7056DRM DRIVERS FOR RENESAS R-CAR
7057M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>7057M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
7058M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>7058M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
7059L: dri-devel@lists.freedesktop.org7059L: dri-devel@lists.freedesktop.org
@@ -7064,7 +7064,16 @@ F: Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml · 4 unmodified lines
7064F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml7064F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml
7065F: Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml7065F: Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml
7066F: Documentation/devicetree/bindings/display/renesas,du.yaml7066F: Documentation/devicetree/bindings/display/renesas,du.yaml
7067F: drivers/gpu/drm/renesas/7067F: drivers/gpu/drm/renesas/rcar-du/
7068
7069DRM DRIVERS FOR RENESAS SHMOBILE
7070M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
7071M: Geert Uytterhoeven <geert+renesas@glider.be>
7072L: dri-devel@lists.freedesktop.org
7073L: linux-renesas-soc@vger.kernel.org
7074S: Supported
7075F: Documentation/devicetree/bindings/display/renesas,shmobile-lcdc.yaml
7076F: drivers/gpu/drm/renesas/shmobile/
7068F: include/linux/platform_data/shmob_drm.h7077F: include/linux/platform_data/shmob_drm.h
7069 7078
7070DRM DRIVERS FOR ROCKCHIP7079DRM DRIVERS FOR ROCKCHIP
drivers/gpu/drm/renesas/shmobile/Kconfig+2−1
@@ -1,11 +1,12 @@
1# SPDX-License-Identifier: GPL-2.01# SPDX-License-Identifier: GPL-2.0
2config DRM_SHMOBILE2config DRM_SHMOBILE
3 tristate "DRM Support for SH Mobile"3 tristate "DRM Support for SH Mobile"
4 depends on DRM4 depends on DRM && PM
5 depends on ARCH_RENESAS || ARCH_SHMOBILE || COMPILE_TEST5 depends on ARCH_RENESAS || ARCH_SHMOBILE || COMPILE_TEST
6 select BACKLIGHT_CLASS_DEVICE6 select BACKLIGHT_CLASS_DEVICE
7 select DRM_KMS_HELPER7 select DRM_KMS_HELPER
8 select DRM_GEM_DMA_HELPER8 select DRM_GEM_DMA_HELPER
9 select VIDEOMODE_HELPERS
9 help10 help
10 Choose this option if you have an SH Mobile chipset.11 Choose this option if you have an SH Mobile chipset.
11 If M is selected the module will be called shmob-drm.12 If M is selected the module will be called shmob-drm.
drivers/gpu/drm/renesas/shmobile/Makefile+1−2
@@ -1,6 +1,5 @@
1# SPDX-License-Identifier: GPL-2.01# SPDX-License-Identifier: GPL-2.0
2shmob-drm-y := shmob_drm_backlight.o \2shmob-drm-y := shmob_drm_crtc.o \
3 shmob_drm_crtc.o \
4 shmob_drm_drv.o \3 shmob_drm_drv.o \
5 shmob_drm_kms.o \4 shmob_drm_kms.o \
6 shmob_drm_plane.o5 shmob_drm_plane.o
drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.c+0−82
@@ -1,82 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * shmob_drm_backlight.c -- SH Mobile DRM Backlight
4 *
5 * Copyright (C) 2012 Renesas Electronics Corporation
6 *
7 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
8 */
9
10#include <linux/backlight.h>
11
12#include "shmob_drm_backlight.h"
13#include "shmob_drm_crtc.h"
14#include "shmob_drm_drv.h"
15
16static int shmob_drm_backlight_update(struct backlight_device *bdev)
17{
18 struct shmob_drm_connector *scon = bl_get_data(bdev);
19 struct shmob_drm_device *sdev = scon->connector.dev->dev_private;
20 const struct shmob_drm_backlight_data *bdata = &sdev->pdata->backlight;
21 int brightness = backlight_get_brightness(bdev);
22
23 return bdata->set_brightness(brightness);
24}
25
26static int shmob_drm_backlight_get_brightness(struct backlight_device *bdev)
27{
28 struct shmob_drm_connector *scon = bl_get_data(bdev);
29 struct shmob_drm_device *sdev = scon->connector.dev->dev_private;
30 const struct shmob_drm_backlight_data *bdata = &sdev->pdata->backlight;
31
32 return bdata->get_brightness();
33}
34
35static const struct backlight_ops shmob_drm_backlight_ops = {
36 .options = BL_CORE_SUSPENDRESUME,
37 .update_status = shmob_drm_backlight_update,
38 .get_brightness = shmob_drm_backlight_get_brightness,
39};
40
41void shmob_drm_backlight_dpms(struct shmob_drm_connector *scon, int mode)
42{
43 if (scon->backlight == NULL)
44 return;
45
46 scon->backlight->props.power = mode == DRM_MODE_DPMS_ON
47 ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
48 backlight_update_status(scon->backlight);
49}
50
51int shmob_drm_backlight_init(struct shmob_drm_connector *scon)
52{
53 struct shmob_drm_device *sdev = scon->connector.dev->dev_private;
54 const struct shmob_drm_backlight_data *bdata = &sdev->pdata->backlight;
55 struct drm_connector *connector = &scon->connector;
56 struct drm_device *dev = connector->dev;
57 struct backlight_device *backlight;
58
59 if (!bdata->max_brightness)
60 return 0;
61
62 backlight = backlight_device_register(bdata->name, dev->dev, scon,
63 &shmob_drm_backlight_ops, NULL);
64 if (IS_ERR(backlight)) {
65 dev_err(dev->dev, "unable to register backlight device: %ld\n",
66 PTR_ERR(backlight));
67 return PTR_ERR(backlight);
68 }
69
70 backlight->props.max_brightness = bdata->max_brightness;
71 backlight->props.brightness = bdata->max_brightness;
72 backlight->props.power = FB_BLANK_POWERDOWN;
73 backlight_update_status(backlight);
74
75 scon->backlight = backlight;
76 return 0;
77}
78
79void shmob_drm_backlight_exit(struct shmob_drm_connector *scon)
80{
81 backlight_device_unregister(scon->backlight);
82}
drivers/gpu/drm/renesas/shmobile/shmob_drm_backlight.h+0−19
@@ -1,19 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * shmob_drm_backlight.h -- SH Mobile DRM Backlight
4 *
5 * Copyright (C) 2012 Renesas Electronics Corporation
6 *
7 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
8 */
9
10#ifndef __SHMOB_DRM_BACKLIGHT_H__
11#define __SHMOB_DRM_BACKLIGHT_H__
12
13struct shmob_drm_connector;
14
15void shmob_drm_backlight_dpms(struct shmob_drm_connector *scon, int mode);
16int shmob_drm_backlight_init(struct shmob_drm_connector *scon);
17void shmob_drm_backlight_exit(struct shmob_drm_connector *scon);
18
19#endif /* __SHMOB_DRM_BACKLIGHT_H__ */
drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c+280−370
@@ -7,9 +7,18 @@ · 6 unmodified lines
7 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)7 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
8 */8 */
9 9
10#include <linux/backlight.h>
11#include <linux/clk.h>10#include <linux/clk.h>
12 11#include <linux/media-bus-format.h>
12#include <linux/of.h>
13#include <linux/of_graph.h>
14#include <linux/pm_runtime.h>
15
16#include <drm/drm_atomic.h>
17#include <drm/drm_atomic_helper.h>
18#include <drm/drm_atomic_state_helper.h>
19#include <drm/drm_atomic_uapi.h>
20#include <drm/drm_bridge.h>
21#include <drm/drm_bridge_connector.h>
13#include <drm/drm_crtc.h>22#include <drm/drm_crtc.h>
14#include <drm/drm_crtc_helper.h>23#include <drm/drm_crtc_helper.h>
15#include <drm/drm_fb_dma_helper.h>24#include <drm/drm_fb_dma_helper.h>
@@ -18,85 +27,123 @@ · 2 unmodified lines
18#include <drm/drm_gem_dma_helper.h>27#include <drm/drm_gem_dma_helper.h>
19#include <drm/drm_modeset_helper.h>28#include <drm/drm_modeset_helper.h>
20#include <drm/drm_modeset_helper_vtables.h>29#include <drm/drm_modeset_helper_vtables.h>
21#include <drm/drm_plane_helper.h>30#include <drm/drm_panel.h>
22#include <drm/drm_probe_helper.h>31#include <drm/drm_probe_helper.h>
23#include <drm/drm_simple_kms_helper.h>32#include <drm/drm_simple_kms_helper.h>
24#include <drm/drm_vblank.h>33#include <drm/drm_vblank.h>
25 34
26#include "shmob_drm_backlight.h"35#include <video/videomode.h>
36
27#include "shmob_drm_crtc.h"37#include "shmob_drm_crtc.h"
28#include "shmob_drm_drv.h"38#include "shmob_drm_drv.h"
29#include "shmob_drm_kms.h"39#include "shmob_drm_kms.h"
30#include "shmob_drm_plane.h"40#include "shmob_drm_plane.h"
31#include "shmob_drm_regs.h"41#include "shmob_drm_regs.h"
32 42
33/*
34 * TODO: panel support
35 */
36
37/* -----------------------------------------------------------------------------43/* -----------------------------------------------------------------------------
38 * Clock management44 * Page Flip
39 */45 */
40 46
41static int shmob_drm_clk_on(struct shmob_drm_device *sdev)47void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc)
42{48{
43 int ret;49 struct drm_pending_vblank_event *event;
50 struct drm_device *dev = scrtc->base.dev;
51 unsigned long flags;
44 52
45 if (sdev->clock) {53 spin_lock_irqsave(&dev->event_lock, flags);
46 ret = clk_prepare_enable(sdev->clock);54 event = scrtc->event;
47 if (ret < 0)55 scrtc->event = NULL;
48 return ret;56 if (event) {
57 drm_crtc_send_vblank_event(&scrtc->base, event);
58 wake_up(&scrtc->flip_wait);
59 drm_crtc_vblank_put(&scrtc->base);
49 }60 }
61 spin_unlock_irqrestore(&dev->event_lock, flags);
62}
50 63
51 return 0;64static bool shmob_drm_crtc_page_flip_pending(struct shmob_drm_crtc *scrtc)
65{
66 struct drm_device *dev = scrtc->base.dev;
67 unsigned long flags;
68 bool pending;
69
70 spin_lock_irqsave(&dev->event_lock, flags);
71 pending = scrtc->event != NULL;
72 spin_unlock_irqrestore(&dev->event_lock, flags);
73
74 return pending;
52}75}
53 76
54static void shmob_drm_clk_off(struct shmob_drm_device *sdev)77static void shmob_drm_crtc_wait_page_flip(struct shmob_drm_crtc *scrtc)
55{78{
56 if (sdev->clock)79 struct drm_crtc *crtc = &scrtc->base;
57 clk_disable_unprepare(sdev->clock);80 struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
81
82 if (wait_event_timeout(scrtc->flip_wait,
83 !shmob_drm_crtc_page_flip_pending(scrtc),
84 msecs_to_jiffies(50)))
85 return;
86
87 dev_warn(sdev->dev, "page flip timeout\n");
88
89 shmob_drm_crtc_finish_page_flip(scrtc);
58}90}
59 91
60/* -----------------------------------------------------------------------------92/* -----------------------------------------------------------------------------
61 * CRTC93 * CRTC
62 */94 */
63 95
96static const struct {
97 u32 fmt;
98 u32 ldmt1r;
99} shmob_drm_bus_fmts[] = {
100 { MEDIA_BUS_FMT_RGB888_3X8, LDMT1R_MIFTYP_RGB8 },
101 { MEDIA_BUS_FMT_RGB666_2X9_BE, LDMT1R_MIFTYP_RGB9 },
102 { MEDIA_BUS_FMT_RGB888_2X12_BE, LDMT1R_MIFTYP_RGB12A },
103 { MEDIA_BUS_FMT_RGB444_1X12, LDMT1R_MIFTYP_RGB12B },
104 { MEDIA_BUS_FMT_RGB565_1X16, LDMT1R_MIFTYP_RGB16 },
105 { MEDIA_BUS_FMT_RGB666_1X18, LDMT1R_MIFTYP_RGB18 },
106 { MEDIA_BUS_FMT_RGB888_1X24, LDMT1R_MIFTYP_RGB24 },
107 { MEDIA_BUS_FMT_UYVY8_1X16, LDMT1R_MIFTYP_YCBCR },
108};
109
64static void shmob_drm_crtc_setup_geometry(struct shmob_drm_crtc *scrtc)110static void shmob_drm_crtc_setup_geometry(struct shmob_drm_crtc *scrtc)
65{111{
66 struct drm_crtc *crtc = &scrtc->crtc;112 struct drm_crtc *crtc = &scrtc->base;
67 struct shmob_drm_device *sdev = crtc->dev->dev_private;113 struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
68 const struct shmob_drm_interface_data *idata = &sdev->pdata->iface;114 const struct drm_display_info *info = &sdev->connector->display_info;
69 const struct drm_display_mode *mode = &crtc->mode;115 const struct drm_display_mode *mode = &crtc->mode;
116 unsigned int i;
70 u32 value;117 u32 value;
71 118
72 value = sdev->ldmt1r119 if (!info->num_bus_formats || !info->bus_formats) {
73 | ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : LDMT1R_VPOL)120 dev_warn(sdev->dev, "No bus format reported, using RGB888\n");
74 | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : LDMT1R_HPOL)121 value = LDMT1R_MIFTYP_RGB24;
75 | ((idata->flags & SHMOB_DRM_IFACE_FL_DWPOL) ? LDMT1R_DWPOL : 0)122 } else {
76 | ((idata->flags & SHMOB_DRM_IFACE_FL_DIPOL) ? LDMT1R_DIPOL : 0)123 for (i = 0; i < ARRAY_SIZE(shmob_drm_bus_fmts); i++) {
77 | ((idata->flags & SHMOB_DRM_IFACE_FL_DAPOL) ? LDMT1R_DAPOL : 0)124 if (shmob_drm_bus_fmts[i].fmt == info->bus_formats[0])
78 | ((idata->flags & SHMOB_DRM_IFACE_FL_HSCNT) ? LDMT1R_HSCNT : 0)125 break;
79 | ((idata->flags & SHMOB_DRM_IFACE_FL_DWCNT) ? LDMT1R_DWCNT : 0);126 }
80 lcdc_write(sdev, LDMT1R, value);127 if (i < ARRAY_SIZE(shmob_drm_bus_fmts)) {
81 128 value = shmob_drm_bus_fmts[i].ldmt1r;
82 if (idata->interface >= SHMOB_DRM_IFACE_SYS8A &&129 } else {
83 idata->interface <= SHMOB_DRM_IFACE_SYS24) {130 dev_warn(sdev->dev,
84 /* Setup SYS bus. */131 "unsupported bus format 0x%x, using RGB888\n",
85 value = (idata->sys.cs_setup << LDMT2R_CSUP_SHIFT)132 info->bus_formats[0]);
86 | (idata->sys.vsync_active_high ? LDMT2R_RSV : 0)133 value = LDMT1R_MIFTYP_RGB24;
87 | (idata->sys.vsync_dir_input ? LDMT2R_VSEL : 0)134 }
88 | (idata->sys.write_setup << LDMT2R_WCSC_SHIFT)
89 | (idata->sys.write_cycle << LDMT2R_WCEC_SHIFT)
90 | (idata->sys.write_strobe << LDMT2R_WCLW_SHIFT);
91 lcdc_write(sdev, LDMT2R, value);
92
93 value = (idata->sys.read_latch << LDMT3R_RDLC_SHIFT)
94 | (idata->sys.read_setup << LDMT3R_RCSC_SHIFT)
95 | (idata->sys.read_cycle << LDMT3R_RCEC_SHIFT)
96 | (idata->sys.read_strobe << LDMT3R_RCLW_SHIFT);
97 lcdc_write(sdev, LDMT3R, value);
98 }135 }
99 136
137 if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
138 value |= LDMT1R_DWPOL;
139 if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
140 value |= LDMT1R_DIPOL;
141 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
142 value |= LDMT1R_VPOL;
143 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
144 value |= LDMT1R_HPOL;
145 lcdc_write(sdev, LDMT1R, value);
146
100 value = ((mode->hdisplay / 8) << 16) /* HDCN */147 value = ((mode->hdisplay / 8) << 16) /* HDCN */
101 | (mode->htotal / 8); /* HTCN */148 | (mode->htotal / 8); /* HTCN */
102 lcdc_write(sdev, LDHCNR, value);149 lcdc_write(sdev, LDHCNR, value);
@@ -121,7 +168,7 @@ static void shmob_drm_crtc_setup_geometry(struct shmob_drm_crtc *scrtc) · 18 unmodified lines
121 168
122static void shmob_drm_crtc_start_stop(struct shmob_drm_crtc *scrtc, bool start)169static void shmob_drm_crtc_start_stop(struct shmob_drm_crtc *scrtc, bool start)
123{170{
124 struct shmob_drm_device *sdev = scrtc->crtc.dev->dev_private;171 struct shmob_drm_device *sdev = to_shmob_device(scrtc->base.dev);
125 u32 value;172 u32 value;
126 173
127 value = lcdc_read(sdev, LDCNT2R);174 value = lcdc_read(sdev, LDCNT2R);
@@ -145,34 +192,23 @@ static void shmob_drm_crtc_start_stop(struct shmob_drm_crtc *scrtc, bool start) · 17 unmodified lines
145 }192 }
146}193}
147 194
148/*195static inline struct shmob_drm_crtc *to_shmob_crtc(struct drm_crtc *crtc)
149 * shmob_drm_crtc_start - Configure and start the LCDC196{
150 * @scrtc: the SH Mobile CRTC197 return container_of(crtc, struct shmob_drm_crtc, base);
151 *198}
152 * Configure and start the LCDC device. External devices (clocks, MERAM, panels,199
153 * ...) are not touched by this function.200static void shmob_drm_crtc_atomic_enable(struct drm_crtc *crtc,
154 */201 struct drm_atomic_state *state)
155static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
156{202{
157 struct drm_crtc *crtc = &scrtc->crtc;203 struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
158 struct shmob_drm_device *sdev = crtc->dev->dev_private;204 struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
159 const struct shmob_drm_interface_data *idata = &sdev->pdata->iface;205 unsigned int clk_div = sdev->config.clk_div;
160 const struct shmob_drm_format_info *format;206 struct device *dev = sdev->dev;
161 struct drm_device *dev = sdev->ddev;
162 struct drm_plane *plane;
163 u32 value;207 u32 value;
164 int ret;208 int ret;
165 209
166 if (scrtc->started)210 ret = pm_runtime_resume_and_get(dev);
167 return;211 if (ret)
168
169 format = shmob_drm_format_info(crtc->primary->fb->format->format);
170 if (WARN_ON(format == NULL))
171 return;
172
173 /* Enable clocks before accessing the hardware. */
174 ret = shmob_drm_clk_on(sdev);
175 if (ret < 0)
176 return;212 return;
177 213
178 /* Reset and enable the LCDC. */214 /* Reset and enable the LCDC. */
@@ -188,79 +224,50 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc) · 9 unmodified lines
188 lcdc_write(sdev, LDPMR, 0);224 lcdc_write(sdev, LDPMR, 0);
189 225
190 value = sdev->lddckr;226 value = sdev->lddckr;
191 if (idata->clk_div) {227 if (clk_div) {
192 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider228 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
193 * denominator.229 * denominator.
194 */230 */
195 lcdc_write(sdev, LDDCKPAT1R, 0);231 lcdc_write(sdev, LDDCKPAT1R, 0);
196 lcdc_write(sdev, LDDCKPAT2R, (1 << (idata->clk_div / 2)) - 1);232 lcdc_write(sdev, LDDCKPAT2R, (1 << (clk_div / 2)) - 1);
197 233
198 if (idata->clk_div == 1)234 if (clk_div == 1)
199 value |= LDDCKR_MOSEL;235 value |= LDDCKR_MOSEL;
200 else236 else
201 value |= idata->clk_div;237 value |= clk_div;
202 }238 }
203 239
204 lcdc_write(sdev, LDDCKR, value);240 lcdc_write(sdev, LDDCKR, value);
205 lcdc_write(sdev, LDDCKSTPR, 0);241 lcdc_write(sdev, LDDCKSTPR, 0);
206 lcdc_wait_bit(sdev, LDDCKSTPR, ~0, 0);242 lcdc_wait_bit(sdev, LDDCKSTPR, ~0, 0);
207 243
208 /* TODO: Setup SYS panel */
209
210 /* Setup geometry, format, frame buffer memory and operation mode. */244 /* Setup geometry, format, frame buffer memory and operation mode. */
211 shmob_drm_crtc_setup_geometry(scrtc);245 shmob_drm_crtc_setup_geometry(scrtc);
212 246
213 /* TODO: Handle YUV colorspaces. Hardcode REC709 for now. */
214 lcdc_write(sdev, LDDFR, format->lddfr | LDDFR_CF1);
215 lcdc_write(sdev, LDMLSR, scrtc->line_size);
216 lcdc_write(sdev, LDSA1R, scrtc->dma[0]);
217 if (format->yuv)
218 lcdc_write(sdev, LDSA2R, scrtc->dma[1]);
219 lcdc_write(sdev, LDSM1R, 0);247 lcdc_write(sdev, LDSM1R, 0);
220 248
221 /* Word and long word swap. */
222 switch (format->fourcc) {
223 case DRM_FORMAT_RGB565:
224 case DRM_FORMAT_NV21:
225 case DRM_FORMAT_NV61:
226 case DRM_FORMAT_NV42:
227 value = LDDDSR_LS | LDDDSR_WS;
228 break;
229 case DRM_FORMAT_RGB888:
230 case DRM_FORMAT_NV12:
231 case DRM_FORMAT_NV16:
232 case DRM_FORMAT_NV24:
233 value = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
234 break;
235 case DRM_FORMAT_ARGB8888:
236 case DRM_FORMAT_XRGB8888:
237 default:
238 value = LDDDSR_LS;
239 break;
240 }
241 lcdc_write(sdev, LDDDSR, value);
242
243 /* Setup planes. */
244 drm_for_each_legacy_plane(plane, dev) {
245 if (plane->crtc == crtc)
246 shmob_drm_plane_setup(plane);
247 }
248
249 /* Enable the display output. */249 /* Enable the display output. */
250 lcdc_write(sdev, LDCNT1R, LDCNT1R_DE);250 lcdc_write(sdev, LDCNT1R, LDCNT1R_DE);
251 251
252 shmob_drm_crtc_start_stop(scrtc, true);252 shmob_drm_crtc_start_stop(scrtc, true);
253 253
254 scrtc->started = true;254 /* Turn vertical blank interrupt reporting back on. */
255 drm_crtc_vblank_on(crtc);
255}256}
256 257
257static void shmob_drm_crtc_stop(struct shmob_drm_crtc *scrtc)258static void shmob_drm_crtc_atomic_disable(struct drm_crtc *crtc,
259 struct drm_atomic_state *state)
258{260{
259 struct drm_crtc *crtc = &scrtc->crtc;261 struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
260 struct shmob_drm_device *sdev = crtc->dev->dev_private;262 struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
261 263
262 if (!scrtc->started)264 /*
263 return;265 * Disable vertical blank interrupt reporting. We first need to wait
266 * for page flip completion before stopping the CRTC as userspace
267 * expects page flips to eventually complete.
268 */
269 shmob_drm_crtc_wait_page_flip(scrtc);
270 drm_crtc_vblank_off(crtc);
264 271
265 /* Stop the LCDC. */272 /* Stop the LCDC. */
266 shmob_drm_crtc_start_stop(scrtc, false);273 shmob_drm_crtc_start_stop(scrtc, false);
@@ -268,145 +275,31 @@ static void shmob_drm_crtc_stop(struct shmob_drm_crtc *scrtc) · 1 unmodified line
268 /* Disable the display output. */275 /* Disable the display output. */
269 lcdc_write(sdev, LDCNT1R, 0);276 lcdc_write(sdev, LDCNT1R, 0);
270 277
271 /* Stop clocks. */278 pm_runtime_put(sdev->dev);
272 shmob_drm_clk_off(sdev);
273
274 scrtc->started = false;
275}
276
277void shmob_drm_crtc_suspend(struct shmob_drm_crtc *scrtc)
278{
279 shmob_drm_crtc_stop(scrtc);
280}
281
282void shmob_drm_crtc_resume(struct shmob_drm_crtc *scrtc)
283{
284 if (scrtc->dpms != DRM_MODE_DPMS_ON)
285 return;
286
287 shmob_drm_crtc_start(scrtc);
288}279}
289 280
290static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc,281static void shmob_drm_crtc_atomic_flush(struct drm_crtc *crtc,
291 int x, int y)282 struct drm_atomic_state *state)
292{283{
293 struct drm_crtc *crtc = &scrtc->crtc;284 struct drm_pending_vblank_event *event;
294 struct drm_framebuffer *fb = crtc->primary->fb;285 struct drm_device *dev = crtc->dev;
295 struct drm_gem_dma_object *gem;286 unsigned long flags;
296 unsigned int bpp;
297
298 bpp = scrtc->format->yuv ? 8 : scrtc->format->bpp;
299 gem = drm_fb_dma_get_gem_obj(fb, 0);
300 scrtc->dma[0] = gem->dma_addr + fb->offsets[0]
301 + y * fb->pitches[0] + x * bpp / 8;
302
303 if (scrtc->format->yuv) {
304 bpp = scrtc->format->bpp - 8;
305 gem = drm_fb_dma_get_gem_obj(fb, 1);
306 scrtc->dma[1] = gem->dma_addr + fb->offsets[1]
307 + y / (bpp == 4 ? 2 : 1) * fb->pitches[1]
308 + x * (bpp == 16 ? 2 : 1);
309 }
310}
311
312static void shmob_drm_crtc_update_base(struct shmob_drm_crtc *scrtc)
313{
314 struct drm_crtc *crtc = &scrtc->crtc;
315 struct shmob_drm_device *sdev = crtc->dev->dev_private;
316
317 shmob_drm_crtc_compute_base(scrtc, crtc->x, crtc->y);
318
319 lcdc_write_mirror(sdev, LDSA1R, scrtc->dma[0]);
320 if (scrtc->format->yuv)
321 lcdc_write_mirror(sdev, LDSA2R, scrtc->dma[1]);
322
323 lcdc_write(sdev, LDRCNTR, lcdc_read(sdev, LDRCNTR) ^ LDRCNTR_MRS);
324}
325
326#define to_shmob_crtc(c) container_of(c, struct shmob_drm_crtc, crtc)
327
328static void shmob_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
329{
330 struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
331
332 if (scrtc->dpms == mode)
333 return;
334
335 if (mode == DRM_MODE_DPMS_ON)
336 shmob_drm_crtc_start(scrtc);
337 else
338 shmob_drm_crtc_stop(scrtc);
339
340 scrtc->dpms = mode;
341}
342
343static void shmob_drm_crtc_mode_prepare(struct drm_crtc *crtc)
344{
345 shmob_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
346}
347 287
348static int shmob_drm_crtc_mode_set(struct drm_crtc *crtc,288 if (crtc->state->event) {
349 struct drm_display_mode *mode,289 spin_lock_irqsave(&dev->event_lock, flags);
350 struct drm_display_mode *adjusted_mode,290 event = crtc->state->event;
351 int x, int y,291 crtc->state->event = NULL;
352 struct drm_framebuffer *old_fb)292 drm_crtc_send_vblank_event(crtc, event);
353{293 spin_unlock_irqrestore(&dev->event_lock, flags);
354 struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
355 struct shmob_drm_device *sdev = crtc->dev->dev_private;
356 const struct shmob_drm_format_info *format;
357
358 format = shmob_drm_format_info(crtc->primary->fb->format->format);
359 if (format == NULL) {
360 dev_dbg(sdev->dev, "mode_set: unsupported format %p4cc\n",
361 &crtc->primary->fb->format->format);
362 return -EINVAL;
363 }294 }
364
365 scrtc->format = format;
366 scrtc->line_size = crtc->primary->fb->pitches[0];
367
368 shmob_drm_crtc_compute_base(scrtc, x, y);
369
370 return 0;
371}
372
373static void shmob_drm_crtc_mode_commit(struct drm_crtc *crtc)
374{
375 shmob_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
376}
377
378static int shmob_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
379 struct drm_framebuffer *old_fb)
380{
381 shmob_drm_crtc_update_base(to_shmob_crtc(crtc));
382
383 return 0;
384}295}
385 296
386static const struct drm_crtc_helper_funcs crtc_helper_funcs = {297static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
387 .dpms = shmob_drm_crtc_dpms,298 .atomic_flush = shmob_drm_crtc_atomic_flush,
388 .prepare = shmob_drm_crtc_mode_prepare,299 .atomic_enable = shmob_drm_crtc_atomic_enable,
389 .commit = shmob_drm_crtc_mode_commit,300 .atomic_disable = shmob_drm_crtc_atomic_disable,
390 .mode_set = shmob_drm_crtc_mode_set,
391 .mode_set_base = shmob_drm_crtc_mode_set_base,
392};301};
393 302
394void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc)
395{
396 struct drm_pending_vblank_event *event;
397 struct drm_device *dev = scrtc->crtc.dev;
398 unsigned long flags;
399
400 spin_lock_irqsave(&dev->event_lock, flags);
401 event = scrtc->event;
402 scrtc->event = NULL;
403 if (event) {
404 drm_crtc_send_vblank_event(&scrtc->crtc, event);
405 drm_crtc_vblank_put(&scrtc->crtc);
406 }
407 spin_unlock_irqrestore(&dev->event_lock, flags);
408}
409
410static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,303static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
411 struct drm_framebuffer *fb,304 struct drm_framebuffer *fb,
412 struct drm_pending_vblank_event *event,305 struct drm_pending_vblank_event *event,
@@ -414,7 +307,7 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc, · 1 unmodified line
414 struct drm_modeset_acquire_ctx *ctx)307 struct drm_modeset_acquire_ctx *ctx)
415{308{
416 struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);309 struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
417 struct drm_device *dev = scrtc->crtc.dev;310 struct drm_device *dev = scrtc->base.dev;
418 unsigned long flags;311 unsigned long flags;
419 312
420 spin_lock_irqsave(&dev->event_lock, flags);313 spin_lock_irqsave(&dev->event_lock, flags);
@@ -424,12 +317,11 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc, · 3 unmodified lines
424 }317 }
425 spin_unlock_irqrestore(&dev->event_lock, flags);318 spin_unlock_irqrestore(&dev->event_lock, flags);
426 319
427 crtc->primary->fb = fb;320 drm_atomic_set_fb_for_plane(crtc->primary->state, fb);
428 shmob_drm_crtc_update_base(scrtc);
429 321
430 if (event) {322 if (event) {
431 event->pipe = 0;323 event->pipe = 0;
432 drm_crtc_vblank_get(&scrtc->crtc);324 drm_crtc_vblank_get(&scrtc->base);
433 spin_lock_irqsave(&dev->event_lock, flags);325 spin_lock_irqsave(&dev->event_lock, flags);
434 scrtc->event = event;326 scrtc->event = event;
435 spin_unlock_irqrestore(&dev->event_lock, flags);327 spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -457,7 +349,7 @@ static void shmob_drm_crtc_enable_vblank(struct shmob_drm_device *sdev, · 21 unmodified lines
457 349
458static int shmob_drm_enable_vblank(struct drm_crtc *crtc)350static int shmob_drm_enable_vblank(struct drm_crtc *crtc)
459{351{
460 struct shmob_drm_device *sdev = crtc->dev->dev_private;352 struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
461 353
462 shmob_drm_crtc_enable_vblank(sdev, true);354 shmob_drm_crtc_enable_vblank(sdev, true);
463 355
@@ -466,88 +358,65 @@ static int shmob_drm_enable_vblank(struct drm_crtc *crtc) · 2 unmodified lines
466 358
467static void shmob_drm_disable_vblank(struct drm_crtc *crtc)359static void shmob_drm_disable_vblank(struct drm_crtc *crtc)
468{360{
469 struct shmob_drm_device *sdev = crtc->dev->dev_private;361 struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
470 362
471 shmob_drm_crtc_enable_vblank(sdev, false);363 shmob_drm_crtc_enable_vblank(sdev, false);
472}364}
473 365
474static const struct drm_crtc_funcs crtc_funcs = {366static const struct drm_crtc_funcs crtc_funcs = {
367 .reset = drm_atomic_helper_crtc_reset,
475 .destroy = drm_crtc_cleanup,368 .destroy = drm_crtc_cleanup,
476 .set_config = drm_crtc_helper_set_config,369 .set_config = drm_atomic_helper_set_config,
477 .page_flip = shmob_drm_crtc_page_flip,370 .page_flip = shmob_drm_crtc_page_flip,
371 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
372 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
478 .enable_vblank = shmob_drm_enable_vblank,373 .enable_vblank = shmob_drm_enable_vblank,
479 .disable_vblank = shmob_drm_disable_vblank,374 .disable_vblank = shmob_drm_disable_vblank,
480};375};
481 376
482static const uint32_t modeset_formats[] = {
483 DRM_FORMAT_RGB565,
484 DRM_FORMAT_RGB888,
485 DRM_FORMAT_ARGB8888,
486 DRM_FORMAT_XRGB8888,
487};
488
489static const struct drm_plane_funcs primary_plane_funcs = {
490 DRM_PLANE_NON_ATOMIC_FUNCS,
491};
492
493int shmob_drm_crtc_create(struct shmob_drm_device *sdev)377int shmob_drm_crtc_create(struct shmob_drm_device *sdev)
494{378{
495 struct drm_crtc *crtc = &sdev->crtc.crtc;379 struct drm_crtc *crtc = &sdev->crtc.base;
496 struct drm_plane *primary;380 struct drm_plane *primary, *plane;
381 unsigned int i;
497 int ret;382 int ret;
498 383
499 sdev->crtc.dpms = DRM_MODE_DPMS_OFF;384 init_waitqueue_head(&sdev->crtc.flip_wait);
500 385
501 primary = __drm_universal_plane_alloc(sdev->ddev, sizeof(*primary), 0,386 primary = shmob_drm_plane_create(sdev, DRM_PLANE_TYPE_PRIMARY, 0);
502 0, &primary_plane_funcs,
503 modeset_formats,
504 ARRAY_SIZE(modeset_formats),
505 NULL, DRM_PLANE_TYPE_PRIMARY,
506 NULL);
507 if (IS_ERR(primary))387 if (IS_ERR(primary))
508 return PTR_ERR(primary);388 return PTR_ERR(primary);
509 389
510 ret = drm_crtc_init_with_planes(sdev->ddev, crtc, primary, NULL,390 for (i = 1; i < 5; ++i) {
391 plane = shmob_drm_plane_create(sdev, DRM_PLANE_TYPE_OVERLAY, i);
392 if (IS_ERR(plane))
393 return PTR_ERR(plane);
394 }
395
396 ret = drm_crtc_init_with_planes(&sdev->ddev, crtc, primary, NULL,
511 &crtc_funcs, NULL);397 &crtc_funcs, NULL);
512 if (ret < 0) {398 if (ret < 0)
513 drm_plane_cleanup(primary);
514 kfree(primary);
515 return ret;399 return ret;
516 }
517 400
518 drm_crtc_helper_add(crtc, &crtc_helper_funcs);401 drm_crtc_helper_add(crtc, &crtc_helper_funcs);
519 402
403 /* Start with vertical blank interrupt reporting disabled. */
404 drm_crtc_vblank_off(crtc);
405
520 return 0;406 return 0;
521}407}
522 408
523/* -----------------------------------------------------------------------------409/* -----------------------------------------------------------------------------
524 * Encoder410 * Legacy Encoder
525 */411 */
526 412
527#define to_shmob_encoder(e) \
528 container_of(e, struct shmob_drm_encoder, encoder)
529
530static void shmob_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
531{
532 struct shmob_drm_encoder *senc = to_shmob_encoder(encoder);
533 struct shmob_drm_device *sdev = encoder->dev->dev_private;
534 struct shmob_drm_connector *scon = &sdev->connector;
535
536 if (senc->dpms == mode)
537 return;
538
539 shmob_drm_backlight_dpms(scon, mode);
540
541 senc->dpms = mode;
542}
543
544static bool shmob_drm_encoder_mode_fixup(struct drm_encoder *encoder,413static bool shmob_drm_encoder_mode_fixup(struct drm_encoder *encoder,
545 const struct drm_display_mode *mode,414 const struct drm_display_mode *mode,
546 struct drm_display_mode *adjusted_mode)415 struct drm_display_mode *adjusted_mode)
547{416{
548 struct drm_device *dev = encoder->dev;417 struct drm_device *dev = encoder->dev;
549 struct shmob_drm_device *sdev = dev->dev_private;418 struct shmob_drm_device *sdev = to_shmob_device(dev);
550 struct drm_connector *connector = &sdev->connector.connector;419 struct drm_connector *connector = sdev->connector;
551 const struct drm_display_mode *panel_mode;420 const struct drm_display_mode *panel_mode;
552 421
553 if (list_empty(&connector->modes)) {422 if (list_empty(&connector->modes)) {
@@ -563,60 +432,61 @@ static bool shmob_drm_encoder_mode_fixup(struct drm_encoder *encoder, · 9 unmodified lines
563 return true;432 return true;
564}433}
565 434
566static void shmob_drm_encoder_mode_prepare(struct drm_encoder *encoder)
567{
568 /* No-op, everything is handled in the CRTC code. */
569}
570
571static void shmob_drm_encoder_mode_set(struct drm_encoder *encoder,
572 struct drm_display_mode *mode,
573 struct drm_display_mode *adjusted_mode)
574{
575 /* No-op, everything is handled in the CRTC code. */
576}
577
578static void shmob_drm_encoder_mode_commit(struct drm_encoder *encoder)
579{
580 /* No-op, everything is handled in the CRTC code. */
581}
582
583static const struct drm_encoder_helper_funcs encoder_helper_funcs = {435static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
584 .dpms = shmob_drm_encoder_dpms,
585 .mode_fixup = shmob_drm_encoder_mode_fixup,436 .mode_fixup = shmob_drm_encoder_mode_fixup,
586 .prepare = shmob_drm_encoder_mode_prepare,
587 .commit = shmob_drm_encoder_mode_commit,
588 .mode_set = shmob_drm_encoder_mode_set,
589};437};
590 438
439/* -----------------------------------------------------------------------------
440 * Encoder
441 */
442
591int shmob_drm_encoder_create(struct shmob_drm_device *sdev)443int shmob_drm_encoder_create(struct shmob_drm_device *sdev)
592{444{
593 struct drm_encoder *encoder = &sdev->encoder.encoder;445 struct drm_encoder *encoder = &sdev->encoder;
446 struct drm_bridge *bridge;
594 int ret;447 int ret;
595 448
596 sdev->encoder.dpms = DRM_MODE_DPMS_OFF;
597
598 encoder->possible_crtcs = 1;449 encoder->possible_crtcs = 1;
599 450
600 ret = drm_simple_encoder_init(sdev->ddev, encoder,451 ret = drm_simple_encoder_init(&sdev->ddev, encoder,
601 DRM_MODE_ENCODER_LVDS);452 DRM_MODE_ENCODER_DPI);
602 if (ret < 0)453 if (ret < 0)
603 return ret;454 return ret;
604 455
605 drm_encoder_helper_add(encoder, &encoder_helper_funcs);456 if (sdev->pdata) {
457 drm_encoder_helper_add(encoder, &encoder_helper_funcs);
458 return 0;
459 }
460
461 /* Create a panel bridge */
462 bridge = devm_drm_of_get_bridge(sdev->dev, sdev->dev->of_node, 0, 0);
463 if (IS_ERR(bridge))
464 return PTR_ERR(bridge);
465
466 /* Attach the bridge to the encoder */
467 ret = drm_bridge_attach(encoder, bridge, NULL,
468 DRM_BRIDGE_ATTACH_NO_CONNECTOR);
469 if (ret) {
470 dev_err(sdev->dev, "failed to attach bridge: %pe\n",
471 ERR_PTR(ret));
472 return ret;
473 }
606 474
607 return 0;475 return 0;
608}476}
609 477
610/* -----------------------------------------------------------------------------478/* -----------------------------------------------------------------------------
611 * Connector479 * Legacy Connector
612 */480 */
613 481
614#define to_shmob_connector(c) \482static inline struct shmob_drm_connector *to_shmob_connector(struct drm_connector *connector)
615 container_of(c, struct shmob_drm_connector, connector)483{
484 return container_of(connector, struct shmob_drm_connector, base);
485}
616 486
617static int shmob_drm_connector_get_modes(struct drm_connector *connector)487static int shmob_drm_connector_get_modes(struct drm_connector *connector)
618{488{
619 struct shmob_drm_device *sdev = connector->dev->dev_private;489 struct shmob_drm_connector *scon = to_shmob_connector(connector);
620 struct drm_display_mode *mode;490 struct drm_display_mode *mode;
621 491
622 mode = drm_mode_create(connector->dev);492 mode = drm_mode_create(connector->dev);
@@ -624,22 +494,10 @@ static int shmob_drm_connector_get_modes(struct drm_connector *connector) · 1 unmodified line
624 return 0;494 return 0;
625 495
626 mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;496 mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
627 mode->clock = sdev->pdata->panel.mode.clock;
628 mode->hdisplay = sdev->pdata->panel.mode.hdisplay;
629 mode->hsync_start = sdev->pdata->panel.mode.hsync_start;
630 mode->hsync_end = sdev->pdata->panel.mode.hsync_end;
631 mode->htotal = sdev->pdata->panel.mode.htotal;
632 mode->vdisplay = sdev->pdata->panel.mode.vdisplay;
633 mode->vsync_start = sdev->pdata->panel.mode.vsync_start;
634 mode->vsync_end = sdev->pdata->panel.mode.vsync_end;
635 mode->vtotal = sdev->pdata->panel.mode.vtotal;
636 mode->flags = sdev->pdata->panel.mode.flags;
637
638 drm_mode_set_name(mode);
639 drm_mode_probed_add(connector, mode);
640 497
641 connector->display_info.width_mm = sdev->pdata->panel.width_mm;498 drm_display_mode_from_videomode(scon->mode, mode);
642 connector->display_info.height_mm = sdev->pdata->panel.height_mm;499
500 drm_mode_probed_add(connector, mode);
643 501
644 return 1;502 return 1;
645}503}
@@ -659,54 +517,106 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = { · 13 unmodified lines
659 517
660static void shmob_drm_connector_destroy(struct drm_connector *connector)518static void shmob_drm_connector_destroy(struct drm_connector *connector)
661{519{
662 struct shmob_drm_connector *scon = to_shmob_connector(connector);
663
664 shmob_drm_backlight_exit(scon);
665 drm_connector_unregister(connector);520 drm_connector_unregister(connector);
666 drm_connector_cleanup(connector);521 drm_connector_cleanup(connector);
522
523 kfree(connector);
667}524}
668 525
669static const struct drm_connector_funcs connector_funcs = {526static const struct drm_connector_funcs connector_funcs = {
670 .dpms = drm_helper_connector_dpms,527 .reset = drm_atomic_helper_connector_reset,
671 .fill_modes = drm_helper_probe_single_connector_modes,528 .fill_modes = drm_helper_probe_single_connector_modes,
672 .destroy = shmob_drm_connector_destroy,529 .destroy = shmob_drm_connector_destroy,
530 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
531 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
673};532};
674 533
675int shmob_drm_connector_create(struct shmob_drm_device *sdev,534static struct drm_connector *
676 struct drm_encoder *encoder)535shmob_drm_connector_init(struct shmob_drm_device *sdev,
536 struct drm_encoder *encoder)
677{537{
678 struct drm_connector *connector = &sdev->connector.connector;538 u32 bus_fmt = sdev->pdata->iface.bus_fmt;
539 struct shmob_drm_connector *scon;
540 struct drm_connector *connector;
541 struct drm_display_info *info;
542 unsigned int i;
679 int ret;543 int ret;
680 544
681 sdev->connector.encoder = encoder;545 for (i = 0; i < ARRAY_SIZE(shmob_drm_bus_fmts); i++) {
546 if (shmob_drm_bus_fmts[i].fmt == bus_fmt)
547 break;
548 }
549 if (i == ARRAY_SIZE(shmob_drm_bus_fmts)) {
550 dev_err(sdev->dev, "unsupported bus format 0x%x\n", bus_fmt);
551 return ERR_PTR(-EINVAL);
552 }
682 553
683 connector->display_info.width_mm = sdev->pdata->panel.width_mm;554 scon = kzalloc(sizeof(*scon), GFP_KERNEL);
684 connector->display_info.height_mm = sdev->pdata->panel.height_mm;555 if (!scon)
556 return ERR_PTR(-ENOMEM);
685 557
686 ret = drm_connector_init(sdev->ddev, connector, &connector_funcs,558 connector = &scon->base;
687 DRM_MODE_CONNECTOR_LVDS);559 scon->encoder = encoder;
688 if (ret < 0)560 scon->mode = &sdev->pdata->panel.mode;
689 return ret;561
562 info = &connector->display_info;
563 info->width_mm = sdev->pdata->panel.width_mm;
564 info->height_mm = sdev->pdata->panel.height_mm;
565
566 if (scon->mode->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
567 info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
568 if (scon->mode->flags & DISPLAY_FLAGS_DE_LOW)
569 info->bus_flags |= DRM_BUS_FLAG_DE_LOW;
570
571 ret = drm_display_info_set_bus_formats(info, &bus_fmt, 1);
572 if (ret < 0) {
573 kfree(scon);
574 return ERR_PTR(ret);
575 }
576
577 ret = drm_connector_init(&sdev->ddev, connector, &connector_funcs,
578 DRM_MODE_CONNECTOR_DPI);
579 if (ret < 0) {
580 kfree(scon);
581 return ERR_PTR(ret);
582 }
690 583
691 drm_connector_helper_add(connector, &connector_helper_funcs);584 drm_connector_helper_add(connector, &connector_helper_funcs);
692 585
693 ret = shmob_drm_backlight_init(&sdev->connector);586 return connector;
694 if (ret < 0)587}
695 goto err_cleanup;588
589/* -----------------------------------------------------------------------------
590 * Connector
591 */
592
593int shmob_drm_connector_create(struct shmob_drm_device *sdev,
594 struct drm_encoder *encoder)
595{
596 struct drm_connector *connector;
597 int ret;
598
599 if (sdev->pdata)
600 connector = shmob_drm_connector_init(sdev, encoder);
601 else
602 connector = drm_bridge_connector_init(&sdev->ddev, encoder);
603 if (IS_ERR(connector)) {
604 dev_err(sdev->dev, "failed to created connector: %pe\n",
605 connector);
606 return PTR_ERR(connector);
607 }
696 608
697 ret = drm_connector_attach_encoder(connector, encoder);609 ret = drm_connector_attach_encoder(connector, encoder);
698 if (ret < 0)610 if (ret < 0)
699 goto err_backlight;611 goto error;
612
613 connector->dpms = DRM_MODE_DPMS_OFF;
700 614
701 drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);615 sdev->connector = connector;
702 drm_object_property_set_value(&connector->base,
703 sdev->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
704 616
705 return 0;617 return 0;
706 618
707err_backlight:619error:
708 shmob_drm_backlight_exit(&sdev->connector);
709err_cleanup:
710 drm_connector_cleanup(connector);620 drm_connector_cleanup(connector);
711 return ret;621 return ret;
712}622}
drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.h+9−18
@@ -14,39 +14,30 @@ · 13 unmodified lines
14#include <drm/drm_connector.h>14#include <drm/drm_connector.h>
15#include <drm/drm_encoder.h>15#include <drm/drm_encoder.h>
16 16
17struct backlight_device;17#include <linux/wait.h>
18
19#include <video/videomode.h>
20
18struct drm_pending_vblank_event;21struct drm_pending_vblank_event;
19struct shmob_drm_device;22struct shmob_drm_device;
20struct shmob_drm_format_info;23struct shmob_drm_format_info;
21 24
22struct shmob_drm_crtc {25struct shmob_drm_crtc {
23 struct drm_crtc crtc;26 struct drm_crtc base;
24 27
25 struct drm_pending_vblank_event *event;28 struct drm_pending_vblank_event *event;
26 int dpms;29 wait_queue_head_t flip_wait;
27
28 const struct shmob_drm_format_info *format;
29 unsigned long dma[2];
30 unsigned int line_size;
31 bool started;
32};
33
34struct shmob_drm_encoder {
35 struct drm_encoder encoder;
36 int dpms;
37};30};
38 31
32/* Legacy connector */
39struct shmob_drm_connector {33struct shmob_drm_connector {
40 struct drm_connector connector;34 struct drm_connector base;
41 struct drm_encoder *encoder;35 struct drm_encoder *encoder;
42 36 const struct videomode *mode;
43 struct backlight_device *backlight;
44};37};
45 38
46int shmob_drm_crtc_create(struct shmob_drm_device *sdev);39int shmob_drm_crtc_create(struct shmob_drm_device *sdev);
47void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc);40void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc);
48void shmob_drm_crtc_suspend(struct shmob_drm_crtc *scrtc);
49void shmob_drm_crtc_resume(struct shmob_drm_crtc *scrtc);
50 41
51int shmob_drm_encoder_create(struct shmob_drm_device *sdev);42int shmob_drm_encoder_create(struct shmob_drm_device *sdev);
52int shmob_drm_connector_create(struct shmob_drm_device *sdev,43int shmob_drm_connector_create(struct shmob_drm_device *sdev,
drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c+83−96
@@ -11,13 +11,17 @@ · 10 unmodified lines
11#include <linux/io.h>11#include <linux/io.h>
12#include <linux/mm.h>12#include <linux/mm.h>
13#include <linux/module.h>13#include <linux/module.h>
14#include <linux/of.h>
14#include <linux/platform_device.h>15#include <linux/platform_device.h>
15#include <linux/pm.h>16#include <linux/pm.h>
17#include <linux/pm_runtime.h>
16#include <linux/slab.h>18#include <linux/slab.h>
17 19
20#include <drm/drm_atomic_helper.h>
18#include <drm/drm_drv.h>21#include <drm/drm_drv.h>
19#include <drm/drm_fbdev_generic.h>22#include <drm/drm_fbdev_generic.h>
20#include <drm/drm_gem_dma_helper.h>23#include <drm/drm_gem_dma_helper.h>
24#include <drm/drm_modeset_helper.h>
21#include <drm/drm_module.h>25#include <drm/drm_module.h>
22#include <drm/drm_probe_helper.h>26#include <drm/drm_probe_helper.h>
23#include <drm/drm_vblank.h>27#include <drm/drm_vblank.h>
@@ -31,57 +35,23 @@ · 7 unmodified lines
31 * Hardware initialization35 * Hardware initialization
32 */36 */
33 37
34static int shmob_drm_init_interface(struct shmob_drm_device *sdev)
35{
36 static const u32 ldmt1r[] = {
37 [SHMOB_DRM_IFACE_RGB8] = LDMT1R_MIFTYP_RGB8,
38 [SHMOB_DRM_IFACE_RGB9] = LDMT1R_MIFTYP_RGB9,
39 [SHMOB_DRM_IFACE_RGB12A] = LDMT1R_MIFTYP_RGB12A,
40 [SHMOB_DRM_IFACE_RGB12B] = LDMT1R_MIFTYP_RGB12B,
41 [SHMOB_DRM_IFACE_RGB16] = LDMT1R_MIFTYP_RGB16,
42 [SHMOB_DRM_IFACE_RGB18] = LDMT1R_MIFTYP_RGB18,
43 [SHMOB_DRM_IFACE_RGB24] = LDMT1R_MIFTYP_RGB24,
44 [SHMOB_DRM_IFACE_YUV422] = LDMT1R_MIFTYP_YCBCR,
45 [SHMOB_DRM_IFACE_SYS8A] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8A,
46 [SHMOB_DRM_IFACE_SYS8B] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8B,
47 [SHMOB_DRM_IFACE_SYS8C] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8C,
48 [SHMOB_DRM_IFACE_SYS8D] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8D,
49 [SHMOB_DRM_IFACE_SYS9] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS9,
50 [SHMOB_DRM_IFACE_SYS12] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS12,
51 [SHMOB_DRM_IFACE_SYS16A] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16A,
52 [SHMOB_DRM_IFACE_SYS16B] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16B,
53 [SHMOB_DRM_IFACE_SYS16C] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16C,
54 [SHMOB_DRM_IFACE_SYS18] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS18,
55 [SHMOB_DRM_IFACE_SYS24] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS24,
56 };
57
58 if (sdev->pdata->iface.interface >= ARRAY_SIZE(ldmt1r)) {
59 dev_err(sdev->dev, "invalid interface type %u\n",
60 sdev->pdata->iface.interface);
61 return -EINVAL;
62 }
63
64 sdev->ldmt1r = ldmt1r[sdev->pdata->iface.interface];
65 return 0;
66}
67
68static int shmob_drm_setup_clocks(struct shmob_drm_device *sdev,38static int shmob_drm_setup_clocks(struct shmob_drm_device *sdev,
69 enum shmob_drm_clk_source clksrc)39 enum shmob_drm_clk_source clksrc)
70{40{
71 struct clk *clk;41 struct clk *clk;
72 char *clkname;42 char *clkname;
73 43
74 switch (clksrc) {44 switch (clksrc) {
75 case SHMOB_DRM_CLK_BUS:45 case SHMOB_DRM_CLK_BUS:
76 clkname = "bus_clk";46 clkname = "fck";
77 sdev->lddckr = LDDCKR_ICKSEL_BUS;47 sdev->lddckr = LDDCKR_ICKSEL_BUS;
78 break;48 break;
79 case SHMOB_DRM_CLK_PERIPHERAL:49 case SHMOB_DRM_CLK_PERIPHERAL:
80 clkname = "peripheral_clk";50 clkname = "media";
81 sdev->lddckr = LDDCKR_ICKSEL_MIPI;51 sdev->lddckr = LDDCKR_ICKSEL_MIPI;
82 break;52 break;
83 case SHMOB_DRM_CLK_EXTERNAL:53 case SHMOB_DRM_CLK_EXTERNAL:
84 clkname = NULL;54 clkname = "lclk";
85 sdev->lddckr = LDDCKR_ICKSEL_HDMI;55 sdev->lddckr = LDDCKR_ICKSEL_HDMI;
86 break;56 break;
87 default:57 default:
@@ -105,7 +75,7 @@ static int shmob_drm_setup_clocks(struct shmob_drm_device *sdev, · 17 unmodified lines
105static irqreturn_t shmob_drm_irq(int irq, void *arg)75static irqreturn_t shmob_drm_irq(int irq, void *arg)
106{76{
107 struct drm_device *dev = arg;77 struct drm_device *dev = arg;
108 struct shmob_drm_device *sdev = dev->dev_private;78 struct shmob_drm_device *sdev = to_shmob_device(dev);
109 unsigned long flags;79 unsigned long flags;
110 u32 status;80 u32 status;
111 81
@@ -119,7 +89,7 @@ static irqreturn_t shmob_drm_irq(int irq, void *arg) · 7 unmodified lines
119 spin_unlock_irqrestore(&sdev->irq_lock, flags);89 spin_unlock_irqrestore(&sdev->irq_lock, flags);
120 90
121 if (status & LDINTR_VES) {91 if (status & LDINTR_VES) {
122 drm_handle_vblank(dev, 0);92 drm_crtc_handle_vblank(&sdev->crtc.base);
123 shmob_drm_crtc_finish_page_flip(&sdev->crtc);93 shmob_drm_crtc_finish_page_flip(&sdev->crtc);
124 }94 }
125 95
@@ -129,7 +99,7 @@ static irqreturn_t shmob_drm_irq(int irq, void *arg) · 3 unmodified lines
129DEFINE_DRM_GEM_DMA_FOPS(shmob_drm_fops);99DEFINE_DRM_GEM_DMA_FOPS(shmob_drm_fops);
130 100
131static const struct drm_driver shmob_drm_driver = {101static const struct drm_driver shmob_drm_driver = {
132 .driver_features = DRIVER_GEM | DRIVER_MODESET,102 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
133 DRM_GEM_DMA_DRIVER_OPS,103 DRM_GEM_DMA_DRIVER_OPS,
134 .fops = &shmob_drm_fops,104 .fops = &shmob_drm_fops,
135 .name = "shmob-drm",105 .name = "shmob-drm",
@@ -147,26 +117,45 @@ static int shmob_drm_pm_suspend(struct device *dev) · 11 unmodified lines
147{117{
148 struct shmob_drm_device *sdev = dev_get_drvdata(dev);118 struct shmob_drm_device *sdev = dev_get_drvdata(dev);
149 119
150 drm_kms_helper_poll_disable(sdev->ddev);120 return drm_mode_config_helper_suspend(&sdev->ddev);
151 shmob_drm_crtc_suspend(&sdev->crtc);121}
122
123static int shmob_drm_pm_resume(struct device *dev)
124{
125 struct shmob_drm_device *sdev = dev_get_drvdata(dev);
126
127 return drm_mode_config_helper_resume(&sdev->ddev);
128}
129
130static int shmob_drm_pm_runtime_suspend(struct device *dev)
131{
132 struct shmob_drm_device *sdev = dev_get_drvdata(dev);
133
134 if (sdev->clock)
135 clk_disable_unprepare(sdev->clock);
152 136
153 return 0;137 return 0;
154}138}
155 139
156static int shmob_drm_pm_resume(struct device *dev)140static int shmob_drm_pm_runtime_resume(struct device *dev)
157{141{
158 struct shmob_drm_device *sdev = dev_get_drvdata(dev);142 struct shmob_drm_device *sdev = dev_get_drvdata(dev);
143 int ret;
159 144
160 drm_modeset_lock_all(sdev->ddev);145 if (sdev->clock) {
161 shmob_drm_crtc_resume(&sdev->crtc);146 ret = clk_prepare_enable(sdev->clock);
162 drm_modeset_unlock_all(sdev->ddev);147 if (ret < 0)
148 return ret;
149 }
163 150
164 drm_kms_helper_poll_enable(sdev->ddev);
165 return 0;151 return 0;
166}152}
167 153
168static DEFINE_SIMPLE_DEV_PM_OPS(shmob_drm_pm_ops,154static const struct dev_pm_ops shmob_drm_pm_ops = {
169 shmob_drm_pm_suspend, shmob_drm_pm_resume);155 SYSTEM_SLEEP_PM_OPS(shmob_drm_pm_suspend, shmob_drm_pm_resume)
156 RUNTIME_PM_OPS(shmob_drm_pm_runtime_suspend,
157 shmob_drm_pm_runtime_resume, NULL)
158};
170 159
171/* -----------------------------------------------------------------------------160/* -----------------------------------------------------------------------------
172 * Platform driver161 * Platform driver
@@ -175,37 +164,45 @@ static DEFINE_SIMPLE_DEV_PM_OPS(shmob_drm_pm_ops, · 2 unmodified lines
175static void shmob_drm_remove(struct platform_device *pdev)164static void shmob_drm_remove(struct platform_device *pdev)
176{165{
177 struct shmob_drm_device *sdev = platform_get_drvdata(pdev);166 struct shmob_drm_device *sdev = platform_get_drvdata(pdev);
178 struct drm_device *ddev = sdev->ddev;167 struct drm_device *ddev = &sdev->ddev;
179 168
180 drm_dev_unregister(ddev);169 drm_dev_unregister(ddev);
170 drm_atomic_helper_shutdown(ddev);
181 drm_kms_helper_poll_fini(ddev);171 drm_kms_helper_poll_fini(ddev);
182 free_irq(sdev->irq, ddev);
183 drm_dev_put(ddev);
184}172}
185 173
186static int shmob_drm_probe(struct platform_device *pdev)174static int shmob_drm_probe(struct platform_device *pdev)
187{175{
188 struct shmob_drm_platform_data *pdata = pdev->dev.platform_data;176 struct shmob_drm_platform_data *pdata = pdev->dev.platform_data;
177 const struct shmob_drm_config *config;
189 struct shmob_drm_device *sdev;178 struct shmob_drm_device *sdev;
190 struct drm_device *ddev;179 struct drm_device *ddev;
191 unsigned int i;
192 int ret;180 int ret;
193 181
194 if (pdata == NULL) {182 config = of_device_get_match_data(&pdev->dev);
183 if (!config && !pdata) {
195 dev_err(&pdev->dev, "no platform data\n");184 dev_err(&pdev->dev, "no platform data\n");
196 return -EINVAL;185 return -EINVAL;
197 }186 }
198 187
199 /*188 /*
200 * Allocate and initialize the driver private data, I/O resources and189 * Allocate and initialize the DRM device, driver private data, I/O
201 * clocks.190 * resources and clocks.
202 */191 */
203 sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL);192 sdev = devm_drm_dev_alloc(&pdev->dev, &shmob_drm_driver,
204 if (sdev == NULL)193 struct shmob_drm_device, ddev);
205 return -ENOMEM;194 if (IS_ERR(sdev))
195 return PTR_ERR(sdev);
206 196
197 ddev = &sdev->ddev;
207 sdev->dev = &pdev->dev;198 sdev->dev = &pdev->dev;
208 sdev->pdata = pdata;199 if (config) {
200 sdev->config = *config;
201 } else {
202 sdev->pdata = pdata;
203 sdev->config.clk_source = pdata->clk_source;
204 sdev->config.clk_div = pdata->iface.clk_div;
205 }
209 spin_lock_init(&sdev->irq_lock);206 spin_lock_init(&sdev->irq_lock);
210 207
211 platform_set_drvdata(pdev, sdev);208 platform_set_drvdata(pdev, sdev);
@@ -214,49 +211,32 @@ static int shmob_drm_probe(struct platform_device *pdev) · 2 unmodified lines
214 if (IS_ERR(sdev->mmio))211 if (IS_ERR(sdev->mmio))
215 return PTR_ERR(sdev->mmio);212 return PTR_ERR(sdev->mmio);
216 213
217 ret = shmob_drm_setup_clocks(sdev, pdata->clk_source);214 ret = shmob_drm_setup_clocks(sdev, sdev->config.clk_source);
218 if (ret < 0)215 if (ret < 0)
219 return ret;216 return ret;
220 217
221 ret = shmob_drm_init_interface(sdev);218 ret = devm_pm_runtime_enable(&pdev->dev);
222 if (ret < 0)219 if (ret)
223 return ret;220 return ret;
224 221
225 /* Allocate and initialize the DRM device. */
226 ddev = drm_dev_alloc(&shmob_drm_driver, &pdev->dev);
227 if (IS_ERR(ddev))
228 return PTR_ERR(ddev);
229
230 sdev->ddev = ddev;
231 ddev->dev_private = sdev;
232
233 ret = shmob_drm_modeset_init(sdev);
234 if (ret < 0) {
235 dev_err(&pdev->dev, "failed to initialize mode setting\n");
236 goto err_free_drm_dev;
237 }
238
239 for (i = 0; i < 4; ++i) {
240 ret = shmob_drm_plane_create(sdev, i);
241 if (ret < 0) {
242 dev_err(&pdev->dev, "failed to create plane %u\n", i);
243 goto err_modeset_cleanup;
244 }
245 }
246
247 ret = drm_vblank_init(ddev, 1);222 ret = drm_vblank_init(ddev, 1);
248 if (ret < 0) {223 if (ret < 0) {
249 dev_err(&pdev->dev, "failed to initialize vblank\n");224 dev_err(&pdev->dev, "failed to initialize vblank\n");
250 goto err_modeset_cleanup;225 return ret;
251 }226 }
252 227
228 ret = shmob_drm_modeset_init(sdev);
229 if (ret < 0)
230 return dev_err_probe(&pdev->dev, ret,
231 "failed to initialize mode setting\n");
232
253 ret = platform_get_irq(pdev, 0);233 ret = platform_get_irq(pdev, 0);
254 if (ret < 0)234 if (ret < 0)
255 goto err_modeset_cleanup;235 goto err_modeset_cleanup;
256 sdev->irq = ret;236 sdev->irq = ret;
257 237
258 ret = request_irq(sdev->irq, shmob_drm_irq, 0, ddev->driver->name,238 ret = devm_request_irq(&pdev->dev, sdev->irq, shmob_drm_irq, 0,
259 ddev);239 ddev->driver->name, ddev);
260 if (ret < 0) {240 if (ret < 0) {
261 dev_err(&pdev->dev, "failed to install IRQ handler\n");241 dev_err(&pdev->dev, "failed to install IRQ handler\n");
262 goto err_modeset_cleanup;242 goto err_modeset_cleanup;
@@ -268,28 +248,35 @@ static int shmob_drm_probe(struct platform_device *pdev) · 5 unmodified lines
268 */248 */
269 ret = drm_dev_register(ddev, 0);249 ret = drm_dev_register(ddev, 0);
270 if (ret < 0)250 if (ret < 0)
271 goto err_irq_uninstall;251 goto err_modeset_cleanup;
272 252
273 drm_fbdev_generic_setup(ddev, 16);253 drm_fbdev_generic_setup(ddev, 16);
274 254
275 return 0;255 return 0;
276 256
277err_irq_uninstall:
278 free_irq(sdev->irq, ddev);
279err_modeset_cleanup:257err_modeset_cleanup:
280 drm_kms_helper_poll_fini(ddev);258 drm_kms_helper_poll_fini(ddev);
281err_free_drm_dev:
282 drm_dev_put(ddev);
283
284 return ret;259 return ret;
285}260}
286 261
262static const struct shmob_drm_config shmob_arm_config = {
263 .clk_source = SHMOB_DRM_CLK_BUS,
264 .clk_div = 5,
265};
266
267static const struct of_device_id shmob_drm_of_table[] __maybe_unused = {
268 { .compatible = "renesas,r8a7740-lcdc", .data = &shmob_arm_config, },
269 { .compatible = "renesas,sh73a0-lcdc", .data = &shmob_arm_config, },
270 { /* sentinel */ }
271};
272
287static struct platform_driver shmob_drm_platform_driver = {273static struct platform_driver shmob_drm_platform_driver = {
288 .probe = shmob_drm_probe,274 .probe = shmob_drm_probe,
289 .remove_new = shmob_drm_remove,275 .remove_new = shmob_drm_remove,
290 .driver = {276 .driver = {
291 .name = "shmob-drm",277 .name = "shmob-drm",
292 .pm = pm_sleep_ptr(&shmob_drm_pm_ops),278 .of_match_table = of_match_ptr(shmob_drm_of_table),
279 .pm = &shmob_drm_pm_ops,
293 },280 },
294};281};
295 282
drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.h+14−4
@@ -20,23 +20,33 @@ struct clk; · 19 unmodified lines
20struct device;20struct device;
21struct drm_device;21struct drm_device;
22 22
23struct shmob_drm_config {
24 enum shmob_drm_clk_source clk_source;
25 unsigned int clk_div;
26};
27
23struct shmob_drm_device {28struct shmob_drm_device {
24 struct device *dev;29 struct device *dev;
25 const struct shmob_drm_platform_data *pdata;30 const struct shmob_drm_platform_data *pdata;
31 struct shmob_drm_config config;
26 32
27 void __iomem *mmio;33 void __iomem *mmio;
28 struct clk *clock;34 struct clk *clock;
29 u32 lddckr;35 u32 lddckr;
30 u32 ldmt1r;
31 36
32 unsigned int irq;37 unsigned int irq;
33 spinlock_t irq_lock; /* Protects hardware LDINTR register */38 spinlock_t irq_lock; /* Protects hardware LDINTR register */
34 39
35 struct drm_device *ddev;40 struct drm_device ddev;
36 41
37 struct shmob_drm_crtc crtc;42 struct shmob_drm_crtc crtc;
38 struct shmob_drm_encoder encoder;43 struct drm_encoder encoder;
39 struct shmob_drm_connector connector;44 struct drm_connector *connector;
40};45};
41 46
47static inline struct shmob_drm_device *to_shmob_device(struct drm_device *dev)
48{
49 return container_of(dev, struct shmob_drm_device, ddev);
50}
51
42#endif /* __SHMOB_DRM_DRV_H__ */52#endif /* __SHMOB_DRM_DRV_H__ */
drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.c+55−22
@@ -7,6 +7,7 @@ · 6 unmodified lines
7 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)7 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
8 */8 */
9 9
10#include <drm/drm_atomic_helper.h>
10#include <drm/drm_crtc.h>11#include <drm/drm_crtc.h>
11#include <drm/drm_crtc_helper.h>12#include <drm/drm_crtc_helper.h>
12#include <drm/drm_fourcc.h>13#include <drm/drm_fourcc.h>
@@ -17,6 +18,7 @@ · 4 unmodified lines
17#include "shmob_drm_crtc.h"18#include "shmob_drm_crtc.h"
18#include "shmob_drm_drv.h"19#include "shmob_drm_drv.h"
19#include "shmob_drm_kms.h"20#include "shmob_drm_kms.h"
21#include "shmob_drm_plane.h"
20#include "shmob_drm_regs.h"22#include "shmob_drm_regs.h"
21 23
22/* -----------------------------------------------------------------------------24/* -----------------------------------------------------------------------------
@@ -27,53 +29,73 @@ static const struct shmob_drm_format_info shmob_drm_format_infos[] = { · 4 unmodified lines
27 {29 {
28 .fourcc = DRM_FORMAT_RGB565,30 .fourcc = DRM_FORMAT_RGB565,
29 .bpp = 16,31 .bpp = 16,
30 .yuv = false,
31 .lddfr = LDDFR_PKF_RGB16,32 .lddfr = LDDFR_PKF_RGB16,
33 .ldddsr = LDDDSR_LS | LDDDSR_WS,
34 .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
35 LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16,
32 }, {36 }, {
33 .fourcc = DRM_FORMAT_RGB888,37 .fourcc = DRM_FORMAT_RGB888,
34 .bpp = 24,38 .bpp = 24,
35 .yuv = false,
36 .lddfr = LDDFR_PKF_RGB24,39 .lddfr = LDDFR_PKF_RGB24,
40 .ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
41 .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
42 LDBBSIFR_SWPB | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24,
37 }, {43 }, {
38 .fourcc = DRM_FORMAT_ARGB8888,44 .fourcc = DRM_FORMAT_ARGB8888,
39 .bpp = 32,45 .bpp = 32,
40 .yuv = false,
41 .lddfr = LDDFR_PKF_ARGB32,46 .lddfr = LDDFR_PKF_ARGB32,
47 .ldddsr = LDDDSR_LS,
48 .ldbbsifr = LDBBSIFR_AL_PK | LDBBSIFR_SWPL | LDBBSIFR_RY |
49 LDBBSIFR_RPKF_ARGB32,
42 }, {50 }, {
43 .fourcc = DRM_FORMAT_XRGB8888,51 .fourcc = DRM_FORMAT_XRGB8888,
44 .bpp = 32,52 .bpp = 32,
45 .yuv = false,
46 .lddfr = LDDFR_PKF_ARGB32,53 .lddfr = LDDFR_PKF_ARGB32,
54 .ldddsr = LDDDSR_LS,
55 .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_RY |
56 LDBBSIFR_RPKF_ARGB32,
47 }, {57 }, {
48 .fourcc = DRM_FORMAT_NV12,58 .fourcc = DRM_FORMAT_NV12,
49 .bpp = 12,59 .bpp = 12,
50 .yuv = true,
51 .lddfr = LDDFR_CC | LDDFR_YF_420,60 .lddfr = LDDFR_CC | LDDFR_YF_420,
61 .ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
62 .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
63 LDBBSIFR_SWPB | LDBBSIFR_CHRR_420,
52 }, {64 }, {
53 .fourcc = DRM_FORMAT_NV21,65 .fourcc = DRM_FORMAT_NV21,
54 .bpp = 12,66 .bpp = 12,
55 .yuv = true,
56 .lddfr = LDDFR_CC | LDDFR_YF_420,67 .lddfr = LDDFR_CC | LDDFR_YF_420,
68 .ldddsr = LDDDSR_LS | LDDDSR_WS,
69 .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
70 LDBBSIFR_CHRR_420,
57 }, {71 }, {
58 .fourcc = DRM_FORMAT_NV16,72 .fourcc = DRM_FORMAT_NV16,
59 .bpp = 16,73 .bpp = 16,
60 .yuv = true,
61 .lddfr = LDDFR_CC | LDDFR_YF_422,74 .lddfr = LDDFR_CC | LDDFR_YF_422,
75 .ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
76 .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
77 LDBBSIFR_SWPB | LDBBSIFR_CHRR_422,
62 }, {78 }, {
63 .fourcc = DRM_FORMAT_NV61,79 .fourcc = DRM_FORMAT_NV61,
64 .bpp = 16,80 .bpp = 16,
65 .yuv = true,
66 .lddfr = LDDFR_CC | LDDFR_YF_422,81 .lddfr = LDDFR_CC | LDDFR_YF_422,
82 .ldddsr = LDDDSR_LS | LDDDSR_WS,
83 .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
84 LDBBSIFR_CHRR_422,
67 }, {85 }, {
68 .fourcc = DRM_FORMAT_NV24,86 .fourcc = DRM_FORMAT_NV24,
69 .bpp = 24,87 .bpp = 24,
70 .yuv = true,
71 .lddfr = LDDFR_CC | LDDFR_YF_444,88 .lddfr = LDDFR_CC | LDDFR_YF_444,
89 .ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
90 .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
91 LDBBSIFR_SWPB | LDBBSIFR_CHRR_444,
72 }, {92 }, {
73 .fourcc = DRM_FORMAT_NV42,93 .fourcc = DRM_FORMAT_NV42,
74 .bpp = 24,94 .bpp = 24,
75 .yuv = true,
76 .lddfr = LDDFR_CC | LDDFR_YF_444,95 .lddfr = LDDFR_CC | LDDFR_YF_444,
96 .ldddsr = LDDDSR_LS | LDDDSR_WS,
97 .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
98 LDBBSIFR_CHRR_444,
77 },99 },
78};100};
79 101
@@ -112,7 +134,7 @@ shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv, · 32 unmodified lines
112 return ERR_PTR(-EINVAL);134 return ERR_PTR(-EINVAL);
113 }135 }
114 136
115 if (format->yuv) {137 if (shmob_drm_format_is_yuv(format)) {
116 unsigned int chroma_cpp = format->bpp == 24 ? 2 : 1;138 unsigned int chroma_cpp = format->bpp == 24 ? 2 : 1;
117 139
118 if (mode_cmd->pitches[1] != mode_cmd->pitches[0] * chroma_cpp) {140 if (mode_cmd->pitches[1] != mode_cmd->pitches[0] * chroma_cpp) {
@@ -127,29 +149,40 @@ shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv, · 8 unmodified lines
127 149
128static const struct drm_mode_config_funcs shmob_drm_mode_config_funcs = {150static const struct drm_mode_config_funcs shmob_drm_mode_config_funcs = {
129 .fb_create = shmob_drm_fb_create,151 .fb_create = shmob_drm_fb_create,
152 .atomic_check = drm_atomic_helper_check,
153 .atomic_commit = drm_atomic_helper_commit,
130};154};
131 155
132int shmob_drm_modeset_init(struct shmob_drm_device *sdev)156int shmob_drm_modeset_init(struct shmob_drm_device *sdev)
133{157{
158 struct drm_device *dev = &sdev->ddev;
134 int ret;159 int ret;
135 160
136 ret = drmm_mode_config_init(sdev->ddev);161 ret = drmm_mode_config_init(dev);
137 if (ret)162 if (ret)
138 return ret;163 return ret;
139 164
140 shmob_drm_crtc_create(sdev);165 ret = shmob_drm_crtc_create(sdev);
141 shmob_drm_encoder_create(sdev);166 if (ret < 0)
142 shmob_drm_connector_create(sdev, &sdev->encoder.encoder);167 return ret;
168
169 ret = shmob_drm_encoder_create(sdev);
170 if (ret < 0)
171 return ret;
172
173 ret = shmob_drm_connector_create(sdev, &sdev->encoder);
174 if (ret < 0)
175 return ret;
143 176
144 drm_kms_helper_poll_init(sdev->ddev);177 drm_mode_config_reset(dev);
145 178
146 sdev->ddev->mode_config.min_width = 0;179 drm_kms_helper_poll_init(dev);
147 sdev->ddev->mode_config.min_height = 0;
148 sdev->ddev->mode_config.max_width = 4095;
149 sdev->ddev->mode_config.max_height = 4095;
150 sdev->ddev->mode_config.funcs = &shmob_drm_mode_config_funcs;
151 180
152 drm_helper_disable_unused_functions(sdev->ddev);181 sdev->ddev.mode_config.min_width = 0;
182 sdev->ddev.mode_config.min_height = 0;
183 sdev->ddev.mode_config.max_width = 4095;
184 sdev->ddev.mode_config.max_height = 4095;
185 sdev->ddev.mode_config.funcs = &shmob_drm_mode_config_funcs;
153 186
154 return 0;187 return 0;
155}188}
drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.h+6−3
@@ -17,11 +17,14 @@ struct shmob_drm_device; · 16 unmodified lines
17 17
18struct shmob_drm_format_info {18struct shmob_drm_format_info {
19 u32 fourcc;19 u32 fourcc;
20 unsigned int bpp;20 u32 lddfr; /* LCD Data Format Register */
21 bool yuv;21 u16 ldbbsifr; /* CHn Source Image Format Register low bits */
22 u32 lddfr;22 u8 ldddsr; /* LCDC Input Image Data Swap Register low bits */
23 u8 bpp;
23};24};
24 25
26#define shmob_drm_format_is_yuv(format) ((format)->lddfr & LDDFR_CC)
27
25const struct shmob_drm_format_info *shmob_drm_format_info(u32 fourcc);28const struct shmob_drm_format_info *shmob_drm_format_info(u32 fourcc);
26 29
27int shmob_drm_modeset_init(struct shmob_drm_device *sdev);30int shmob_drm_modeset_init(struct shmob_drm_device *sdev);
drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.c+189−137
@@ -7,11 +7,14 @@ · 6 unmodified lines
7 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)7 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
8 */8 */
9 9
10#include <drm/drm_atomic.h>
11#include <drm/drm_atomic_helper.h>
10#include <drm/drm_crtc.h>12#include <drm/drm_crtc.h>
11#include <drm/drm_fb_dma_helper.h>13#include <drm/drm_fb_dma_helper.h>
12#include <drm/drm_fourcc.h>14#include <drm/drm_fourcc.h>
13#include <drm/drm_framebuffer.h>15#include <drm/drm_framebuffer.h>
14#include <drm/drm_gem_dma_helper.h>16#include <drm/drm_gem_dma_helper.h>
17#include <drm/drm_plane_helper.h>
15 18
16#include "shmob_drm_drv.h"19#include "shmob_drm_drv.h"
17#include "shmob_drm_kms.h"20#include "shmob_drm_kms.h"
@@ -19,102 +22,84 @@ · 1 unmodified line
19#include "shmob_drm_regs.h"22#include "shmob_drm_regs.h"
20 23
21struct shmob_drm_plane {24struct shmob_drm_plane {
22 struct drm_plane plane;25 struct drm_plane base;
23 unsigned int index;26 unsigned int index;
24 unsigned int alpha;27};
28
29struct shmob_drm_plane_state {
30 struct drm_plane_state base;
25 31
26 const struct shmob_drm_format_info *format;32 const struct shmob_drm_format_info *format;
27 unsigned long dma[2];33 u32 dma[2];
28
29 unsigned int src_x;
30 unsigned int src_y;
31 unsigned int crtc_x;
32 unsigned int crtc_y;
33 unsigned int crtc_w;
34 unsigned int crtc_h;
35};34};
36 35
37#define to_shmob_plane(p) container_of(p, struct shmob_drm_plane, plane)36static inline struct shmob_drm_plane *to_shmob_plane(struct drm_plane *plane)
37{
38 return container_of(plane, struct shmob_drm_plane, base);
39}
40
41static inline struct shmob_drm_plane_state *to_shmob_plane_state(struct drm_plane_state *state)
42{
43 return container_of(state, struct shmob_drm_plane_state, base);
44}
38 45
39static void shmob_drm_plane_compute_base(struct shmob_drm_plane *splane,46static void shmob_drm_plane_compute_base(struct shmob_drm_plane_state *sstate)
40 struct drm_framebuffer *fb,
41 int x, int y)
42{47{
48 struct drm_framebuffer *fb = sstate->base.fb;
49 unsigned int x = sstate->base.src_x >> 16;
50 unsigned int y = sstate->base.src_y >> 16;
43 struct drm_gem_dma_object *gem;51 struct drm_gem_dma_object *gem;
44 unsigned int bpp;52 unsigned int bpp;
45 53
46 bpp = splane->format->yuv ? 8 : splane->format->bpp;54 bpp = shmob_drm_format_is_yuv(sstate->format) ? 8 : sstate->format->bpp;
47 gem = drm_fb_dma_get_gem_obj(fb, 0);55 gem = drm_fb_dma_get_gem_obj(fb, 0);
48 splane->dma[0] = gem->dma_addr + fb->offsets[0]56 sstate->dma[0] = gem->dma_addr + fb->offsets[0]
49 + y * fb->pitches[0] + x * bpp / 8;57 + y * fb->pitches[0] + x * bpp / 8;
50 58
51 if (splane->format->yuv) {59 if (shmob_drm_format_is_yuv(sstate->format)) {
52 bpp = splane->format->bpp - 8;60 bpp = sstate->format->bpp - 8;
53 gem = drm_fb_dma_get_gem_obj(fb, 1);61 gem = drm_fb_dma_get_gem_obj(fb, 1);
54 splane->dma[1] = gem->dma_addr + fb->offsets[1]62 sstate->dma[1] = gem->dma_addr + fb->offsets[1]
55 + y / (bpp == 4 ? 2 : 1) * fb->pitches[1]63 + y / (bpp == 4 ? 2 : 1) * fb->pitches[1]
56 + x * (bpp == 16 ? 2 : 1);64 + x * (bpp == 16 ? 2 : 1);
57 }65 }
58}66}
59 67
60static void __shmob_drm_plane_setup(struct shmob_drm_plane *splane,68static void shmob_drm_primary_plane_setup(struct shmob_drm_plane *splane,
61 struct drm_framebuffer *fb)69 struct drm_plane_state *state)
62{70{
63 struct shmob_drm_device *sdev = splane->plane.dev->dev_private;71 struct shmob_drm_plane_state *sstate = to_shmob_plane_state(state);
72 struct shmob_drm_device *sdev = to_shmob_device(splane->base.dev);
73 struct drm_framebuffer *fb = state->fb;
74
75 /* TODO: Handle YUV colorspaces. Hardcode REC709 for now. */
76 lcdc_write(sdev, LDDFR, sstate->format->lddfr | LDDFR_CF1);
77 lcdc_write(sdev, LDMLSR, fb->pitches[0]);
78
79 /* Word and long word swap. */
80 lcdc_write(sdev, LDDDSR, sstate->format->ldddsr);
81
82 lcdc_write_mirror(sdev, LDSA1R, sstate->dma[0]);
83 if (shmob_drm_format_is_yuv(sstate->format))
84 lcdc_write_mirror(sdev, LDSA2R, sstate->dma[1]);
85
86 lcdc_write(sdev, LDRCNTR, lcdc_read(sdev, LDRCNTR) ^ LDRCNTR_MRS);
87}
88
89static void shmob_drm_overlay_plane_setup(struct shmob_drm_plane *splane,
90 struct drm_plane_state *state)
91{
92 struct shmob_drm_plane_state *sstate = to_shmob_plane_state(state);
93 struct shmob_drm_device *sdev = to_shmob_device(splane->base.dev);
94 struct drm_framebuffer *fb = state->fb;
64 u32 format;95 u32 format;
65 96
66 /* TODO: Support ROP3 mode */97 /* TODO: Support ROP3 mode */
67 format = LDBBSIFR_EN | (splane->alpha << LDBBSIFR_LAY_SHIFT);98 format = LDBBSIFR_EN | ((state->alpha >> 8) << LDBBSIFR_LAY_SHIFT) |
68 99 sstate->format->ldbbsifr;
69 switch (splane->format->fourcc) {
70 case DRM_FORMAT_RGB565:
71 case DRM_FORMAT_NV21:
72 case DRM_FORMAT_NV61:
73 case DRM_FORMAT_NV42:
74 format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW;
75 break;
76 case DRM_FORMAT_RGB888:
77 case DRM_FORMAT_NV12:
78 case DRM_FORMAT_NV16:
79 case DRM_FORMAT_NV24:
80 format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB;
81 break;
82 case DRM_FORMAT_ARGB8888:
83 case DRM_FORMAT_XRGB8888:
84 default:
85 format |= LDBBSIFR_SWPL;
86 break;
87 }
88
89 switch (splane->format->fourcc) {
90 case DRM_FORMAT_RGB565:
91 format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16;
92 break;
93 case DRM_FORMAT_RGB888:
94 format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24;
95 break;
96 case DRM_FORMAT_ARGB8888:
97 format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
98 break;
99 case DRM_FORMAT_XRGB8888:
100 format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
101 break;
102 case DRM_FORMAT_NV12:
103 case DRM_FORMAT_NV21:
104 format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420;
105 break;
106 case DRM_FORMAT_NV16:
107 case DRM_FORMAT_NV61:
108 format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422;
109 break;
110 case DRM_FORMAT_NV24:
111 case DRM_FORMAT_NV42:
112 format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444;
113 break;
114 }
115 100
116#define plane_reg_dump(sdev, splane, reg) \101#define plane_reg_dump(sdev, splane, reg) \
117 dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x 0x%08x\n", __func__, \102 dev_dbg(sdev->ddev.dev, "%s(%u): %s 0x%08x 0x%08x\n", __func__, \
118 splane->index, #reg, \103 splane->index, #reg, \
119 lcdc_read(sdev, reg(splane->index)), \104 lcdc_read(sdev, reg(splane->index)), \
120 lcdc_read(sdev, reg(splane->index) + LCDC_SIDE_B_OFFSET))105 lcdc_read(sdev, reg(splane->index) + LCDC_SIDE_B_OFFSET))
@@ -127,29 +112,27 @@ static void __shmob_drm_plane_setup(struct shmob_drm_plane *splane, · 6 unmodified lines
127 plane_reg_dump(sdev, splane, LDBnBSACR);112 plane_reg_dump(sdev, splane, LDBnBSACR);
128 113
129 lcdc_write(sdev, LDBCR, LDBCR_UPC(splane->index));114 lcdc_write(sdev, LDBCR, LDBCR_UPC(splane->index));
130 dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,115 dev_dbg(sdev->ddev.dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,
131 "LDBCR", lcdc_read(sdev, LDBCR));116 "LDBCR", lcdc_read(sdev, LDBCR));
132 117
133 lcdc_write(sdev, LDBnBSIFR(splane->index), format);118 lcdc_write(sdev, LDBnBSIFR(splane->index), format);
134 119
135 lcdc_write(sdev, LDBnBSSZR(splane->index),120 lcdc_write(sdev, LDBnBSSZR(splane->index),
136 (splane->crtc_h << LDBBSSZR_BVSS_SHIFT) |121 (state->crtc_h << LDBBSSZR_BVSS_SHIFT) |
137 (splane->crtc_w << LDBBSSZR_BHSS_SHIFT));122 (state->crtc_w << LDBBSSZR_BHSS_SHIFT));
138 lcdc_write(sdev, LDBnBLOCR(splane->index),123 lcdc_write(sdev, LDBnBLOCR(splane->index),
139 (splane->crtc_y << LDBBLOCR_CVLC_SHIFT) |124 (state->crtc_y << LDBBLOCR_CVLC_SHIFT) |
140 (splane->crtc_x << LDBBLOCR_CHLC_SHIFT));125 (state->crtc_x << LDBBLOCR_CHLC_SHIFT));
141 lcdc_write(sdev, LDBnBSMWR(splane->index),126 lcdc_write(sdev, LDBnBSMWR(splane->index),
142 fb->pitches[0] << LDBBSMWR_BSMW_SHIFT);127 fb->pitches[0] << LDBBSMWR_BSMW_SHIFT);
143 128
144 shmob_drm_plane_compute_base(splane, fb, splane->src_x, splane->src_y);129 lcdc_write(sdev, LDBnBSAYR(splane->index), sstate->dma[0]);
145 130 if (shmob_drm_format_is_yuv(sstate->format))
146 lcdc_write(sdev, LDBnBSAYR(splane->index), splane->dma[0]);131 lcdc_write(sdev, LDBnBSACR(splane->index), sstate->dma[1]);
147 if (splane->format->yuv)
148 lcdc_write(sdev, LDBnBSACR(splane->index), splane->dma[1]);
149 132
150 lcdc_write(sdev, LDBCR,133 lcdc_write(sdev, LDBCR,
151 LDBCR_UPF(splane->index) | LDBCR_UPD(splane->index));134 LDBCR_UPF(splane->index) | LDBCR_UPD(splane->index));
152 dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,135 dev_dbg(sdev->ddev.dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,
153 "LDBCR", lcdc_read(sdev, LDBCR));136 "LDBCR", lcdc_read(sdev, LDBCR));
154 137
155 plane_reg_dump(sdev, splane, LDBnBSIFR);138 plane_reg_dump(sdev, splane, LDBnBSIFR);
@@ -160,75 +143,143 @@ static void __shmob_drm_plane_setup(struct shmob_drm_plane *splane, · 4 unmodified lines
160 plane_reg_dump(sdev, splane, LDBnBSACR);143 plane_reg_dump(sdev, splane, LDBnBSACR);
161}144}
162 145
163void shmob_drm_plane_setup(struct drm_plane *plane)146static int shmob_drm_plane_atomic_check(struct drm_plane *plane,
147 struct drm_atomic_state *state)
164{148{
165 struct shmob_drm_plane *splane = to_shmob_plane(plane);149 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
150 struct shmob_drm_plane_state *sstate = to_shmob_plane_state(new_plane_state);
151 struct drm_crtc_state *crtc_state;
152 bool is_primary = plane->type == DRM_PLANE_TYPE_PRIMARY;
153 int ret;
166 154
167 if (plane->fb == NULL)155 if (!new_plane_state->crtc) {
168 return;156 /*
157 * The visible field is not reset by the DRM core but only
158 * updated by drm_atomic_helper_check_plane_state(), set it
159 * manually.
160 */
161 new_plane_state->visible = false;
162 sstate->format = NULL;
163 return 0;
164 }
169 165
170 __shmob_drm_plane_setup(splane, plane->fb);166 crtc_state = drm_atomic_get_crtc_state(state, new_plane_state->crtc);
171}167 if (IS_ERR(crtc_state))
168 return PTR_ERR(crtc_state);
172 169
173static int170 ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
174shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,171 DRM_PLANE_NO_SCALING,
175 struct drm_framebuffer *fb, int crtc_x, int crtc_y,172 DRM_PLANE_NO_SCALING,
176 unsigned int crtc_w, unsigned int crtc_h,173 !is_primary, true);
177 uint32_t src_x, uint32_t src_y,174 if (ret < 0)
178 uint32_t src_w, uint32_t src_h,175 return ret;
179 struct drm_modeset_acquire_ctx *ctx)
180{
181 struct shmob_drm_plane *splane = to_shmob_plane(plane);
182 struct shmob_drm_device *sdev = plane->dev->dev_private;
183 const struct shmob_drm_format_info *format;
184 176
185 format = shmob_drm_format_info(fb->format->format);177 if (!new_plane_state->visible) {
186 if (format == NULL) {178 sstate->format = NULL;
187 dev_dbg(sdev->dev, "update_plane: unsupported format %08x\n",179 return 0;
188 fb->format->format);
189 return -EINVAL;
190 }180 }
191 181
192 if (src_w >> 16 != crtc_w || src_h >> 16 != crtc_h) {182 sstate->format = shmob_drm_format_info(new_plane_state->fb->format->format);
193 dev_dbg(sdev->dev, "%s: scaling not supported\n", __func__);183 if (!sstate->format) {
184 dev_dbg(plane->dev->dev,
185 "plane_atomic_check: unsupported format %p4cc\n",
186 &new_plane_state->fb->format->format);
194 return -EINVAL;187 return -EINVAL;
195 }188 }
196 189
197 splane->format = format;190 shmob_drm_plane_compute_base(sstate);
198 191
199 splane->src_x = src_x >> 16;
200 splane->src_y = src_y >> 16;
201 splane->crtc_x = crtc_x;
202 splane->crtc_y = crtc_y;
203 splane->crtc_w = crtc_w;
204 splane->crtc_h = crtc_h;
205
206 __shmob_drm_plane_setup(splane, fb);
207 return 0;192 return 0;
208}193}
209 194
210static int shmob_drm_plane_disable(struct drm_plane *plane,195static void shmob_drm_plane_atomic_update(struct drm_plane *plane,
211 struct drm_modeset_acquire_ctx *ctx)196 struct drm_atomic_state *state)
212{197{
198 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
213 struct shmob_drm_plane *splane = to_shmob_plane(plane);199 struct shmob_drm_plane *splane = to_shmob_plane(plane);
214 struct shmob_drm_device *sdev = plane->dev->dev_private;
215 200
216 splane->format = NULL;201 if (!new_plane_state->visible)
202 return;
217 203
204 if (plane->type == DRM_PLANE_TYPE_PRIMARY)
205 shmob_drm_primary_plane_setup(splane, new_plane_state);
206 else
207 shmob_drm_overlay_plane_setup(splane, new_plane_state);
208}
209
210static void shmob_drm_plane_atomic_disable(struct drm_plane *plane,
211 struct drm_atomic_state *state)
212{
213 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
214 struct shmob_drm_device *sdev = to_shmob_device(plane->dev);
215 struct shmob_drm_plane *splane = to_shmob_plane(plane);
216
217 if (!old_state->crtc)
218 return;
219
220 if (plane->type != DRM_PLANE_TYPE_OVERLAY)
221 return;
222
223 lcdc_write(sdev, LDBCR, LDBCR_UPC(splane->index));
218 lcdc_write(sdev, LDBnBSIFR(splane->index), 0);224 lcdc_write(sdev, LDBnBSIFR(splane->index), 0);
219 return 0;225 lcdc_write(sdev, LDBCR,
226 LDBCR_UPF(splane->index) | LDBCR_UPD(splane->index));
220}227}
221 228
222static void shmob_drm_plane_destroy(struct drm_plane *plane)229static struct drm_plane_state *
230shmob_drm_plane_atomic_duplicate_state(struct drm_plane *plane)
223{231{
224 drm_plane_force_disable(plane);232 struct shmob_drm_plane_state *state;
225 drm_plane_cleanup(plane);233 struct shmob_drm_plane_state *copy;
234
235 if (WARN_ON(!plane->state))
236 return NULL;
237
238 state = to_shmob_plane_state(plane->state);
239 copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
240 if (copy == NULL)
241 return NULL;
242
243 __drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
244
245 return &copy->base;
226}246}
227 247
248static void shmob_drm_plane_atomic_destroy_state(struct drm_plane *plane,
249 struct drm_plane_state *state)
250{
251 __drm_atomic_helper_plane_destroy_state(state);
252 kfree(to_shmob_plane_state(state));
253}
254
255static void shmob_drm_plane_reset(struct drm_plane *plane)
256{
257 struct shmob_drm_plane_state *state;
258
259 if (plane->state) {
260 shmob_drm_plane_atomic_destroy_state(plane, plane->state);
261 plane->state = NULL;
262 }
263
264 state = kzalloc(sizeof(*state), GFP_KERNEL);
265 if (state == NULL)
266 return;
267
268 __drm_atomic_helper_plane_reset(plane, &state->base);
269}
270
271static const struct drm_plane_helper_funcs shmob_drm_plane_helper_funcs = {
272 .atomic_check = shmob_drm_plane_atomic_check,
273 .atomic_update = shmob_drm_plane_atomic_update,
274 .atomic_disable = shmob_drm_plane_atomic_disable,
275};
276
228static const struct drm_plane_funcs shmob_drm_plane_funcs = {277static const struct drm_plane_funcs shmob_drm_plane_funcs = {
229 .update_plane = shmob_drm_plane_update,278 .update_plane = drm_atomic_helper_update_plane,
230 .disable_plane = shmob_drm_plane_disable,279 .disable_plane = drm_atomic_helper_disable_plane,
231 .destroy = shmob_drm_plane_destroy,280 .reset = shmob_drm_plane_reset,
281 .atomic_duplicate_state = shmob_drm_plane_atomic_duplicate_state,
282 .atomic_destroy_state = shmob_drm_plane_atomic_destroy_state,
232};283};
233 284
234static const uint32_t formats[] = {285static const uint32_t formats[] = {
@@ -244,22 +295,23 @@ static const uint32_t formats[] = { · 9 unmodified lines
244 DRM_FORMAT_NV42,295 DRM_FORMAT_NV42,
245};296};
246 297
247int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index)298struct drm_plane *shmob_drm_plane_create(struct shmob_drm_device *sdev,
299 enum drm_plane_type type,
300 unsigned int index)
248{301{
249 struct shmob_drm_plane *splane;302 struct shmob_drm_plane *splane;
250 int ret;
251 303
252 splane = devm_kzalloc(sdev->dev, sizeof(*splane), GFP_KERNEL);304 splane = drmm_universal_plane_alloc(&sdev->ddev,
253 if (splane == NULL)305 struct shmob_drm_plane, base, 1,
254 return -ENOMEM;306 &shmob_drm_plane_funcs, formats,
307 ARRAY_SIZE(formats), NULL, type,
308 NULL);
309 if (IS_ERR(splane))
310 return ERR_CAST(splane);
255 311
256 splane->index = index;312 splane->index = index;
257 splane->alpha = 255;
258 313
259 ret = drm_universal_plane_init(sdev->ddev, &splane->plane, 1,314 drm_plane_helper_add(&splane->base, &shmob_drm_plane_helper_funcs);
260 &shmob_drm_plane_funcs,
261 formats, ARRAY_SIZE(formats), NULL,
262 DRM_PLANE_TYPE_OVERLAY, NULL);
263 315
264 return ret;316 return &splane->base;
265}317}
drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.h+3−2
@@ -13,7 +13,8 @@ · 12 unmodified lines
13struct drm_plane;13struct drm_plane;
14struct shmob_drm_device;14struct shmob_drm_device;
15 15
16int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index);16struct drm_plane *shmob_drm_plane_create(struct shmob_drm_device *sdev,
17void shmob_drm_plane_setup(struct drm_plane *plane);17 enum drm_plane_type type,
18 unsigned int index);
18 19
19#endif /* __SHMOB_DRM_PLANE_H__ */20#endif /* __SHMOB_DRM_PLANE_H__ */
include/linux/platform_data/shmob_drm.h+3−54
@@ -10,7 +10,7 @@ · 9 unmodified lines
10#ifndef __SHMOB_DRM_H__10#ifndef __SHMOB_DRM_H__
11#define __SHMOB_DRM_H__11#define __SHMOB_DRM_H__
12 12
13#include <drm/drm_mode.h>13#include <video/videomode.h>
14 14
15enum shmob_drm_clk_source {15enum shmob_drm_clk_source {
16 SHMOB_DRM_CLK_BUS,16 SHMOB_DRM_CLK_BUS,
@@ -18,72 +18,21 @@ enum shmob_drm_clk_source { · 1 unmodified line
18 SHMOB_DRM_CLK_EXTERNAL,18 SHMOB_DRM_CLK_EXTERNAL,
19};19};
20 20
21enum shmob_drm_interface {
22 SHMOB_DRM_IFACE_RGB8, /* 24bpp, 8:8:8 */
23 SHMOB_DRM_IFACE_RGB9, /* 18bpp, 9:9 */
24 SHMOB_DRM_IFACE_RGB12A, /* 24bpp, 12:12 */
25 SHMOB_DRM_IFACE_RGB12B, /* 12bpp */
26 SHMOB_DRM_IFACE_RGB16, /* 16bpp */
27 SHMOB_DRM_IFACE_RGB18, /* 18bpp */
28 SHMOB_DRM_IFACE_RGB24, /* 24bpp */
29 SHMOB_DRM_IFACE_YUV422, /* 16bpp */
30 SHMOB_DRM_IFACE_SYS8A, /* 24bpp, 8:8:8 */
31 SHMOB_DRM_IFACE_SYS8B, /* 18bpp, 8:8:2 */
32 SHMOB_DRM_IFACE_SYS8C, /* 18bpp, 2:8:8 */
33 SHMOB_DRM_IFACE_SYS8D, /* 16bpp, 8:8 */
34 SHMOB_DRM_IFACE_SYS9, /* 18bpp, 9:9 */
35 SHMOB_DRM_IFACE_SYS12, /* 24bpp, 12:12 */
36 SHMOB_DRM_IFACE_SYS16A, /* 16bpp */
37 SHMOB_DRM_IFACE_SYS16B, /* 18bpp, 16:2 */
38 SHMOB_DRM_IFACE_SYS16C, /* 18bpp, 2:16 */
39 SHMOB_DRM_IFACE_SYS18, /* 18bpp */
40 SHMOB_DRM_IFACE_SYS24, /* 24bpp */
41};
42
43struct shmob_drm_backlight_data {
44 const char *name;
45 int max_brightness;
46 int (*get_brightness)(void);
47 int (*set_brightness)(int brightness);
48};
49
50struct shmob_drm_panel_data {21struct shmob_drm_panel_data {
51 unsigned int width_mm; /* Panel width in mm */22 unsigned int width_mm; /* Panel width in mm */
52 unsigned int height_mm; /* Panel height in mm */23 unsigned int height_mm; /* Panel height in mm */
53 struct drm_mode_modeinfo mode;24 struct videomode mode;
54};25};
55 26
56struct shmob_drm_sys_interface_data {
57 unsigned int read_latch:6;
58 unsigned int read_setup:8;
59 unsigned int read_cycle:8;
60 unsigned int read_strobe:8;
61 unsigned int write_setup:8;
62 unsigned int write_cycle:8;
63 unsigned int write_strobe:8;
64 unsigned int cs_setup:3;
65 unsigned int vsync_active_high:1;
66 unsigned int vsync_dir_input:1;
67};
68
69#define SHMOB_DRM_IFACE_FL_DWPOL (1 << 0) /* Rising edge dot clock data latch */
70#define SHMOB_DRM_IFACE_FL_DIPOL (1 << 1) /* Active low display enable */
71#define SHMOB_DRM_IFACE_FL_DAPOL (1 << 2) /* Active low display data */
72#define SHMOB_DRM_IFACE_FL_HSCNT (1 << 3) /* Disable HSYNC during VBLANK */
73#define SHMOB_DRM_IFACE_FL_DWCNT (1 << 4) /* Disable dotclock during blanking */
74
75struct shmob_drm_interface_data {27struct shmob_drm_interface_data {
76 enum shmob_drm_interface interface;28 unsigned int bus_fmt; /* MEDIA_BUS_FMT_* */
77 struct shmob_drm_sys_interface_data sys;
78 unsigned int clk_div;29 unsigned int clk_div;
79 unsigned int flags;
80};30};
81 31
82struct shmob_drm_platform_data {32struct shmob_drm_platform_data {
83 enum shmob_drm_clk_source clk_source;33 enum shmob_drm_clk_source clk_source;
84 struct shmob_drm_interface_data iface;34 struct shmob_drm_interface_data iface;
85 struct shmob_drm_panel_data panel;35 struct shmob_drm_panel_data panel;
86 struct shmob_drm_backlight_data backlight;
87};36};
88 37
89#endif /* __SHMOB_DRM_H__ */38#endif /* __SHMOB_DRM_H__ */
include/uapi/linux/media-bus-format.h+2−1
@@ -34,7 +34,7 @@ · 33 unmodified lines
34 34
35#define MEDIA_BUS_FMT_FIXED 0x000135#define MEDIA_BUS_FMT_FIXED 0x0001
36 36
37/* RGB - next is 0x1025 */37/* RGB - next is 0x1026 */
38#define MEDIA_BUS_FMT_RGB444_1X12 0x101638#define MEDIA_BUS_FMT_RGB444_1X12 0x1016
39#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x100139#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001
40#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x100240#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002
@@ -46,6 +46,7 @@ · 5 unmodified lines
46#define MEDIA_BUS_FMT_RGB565_2X8_BE 0x100746#define MEDIA_BUS_FMT_RGB565_2X8_BE 0x1007
47#define MEDIA_BUS_FMT_RGB565_2X8_LE 0x100847#define MEDIA_BUS_FMT_RGB565_2X8_LE 0x1008
48#define MEDIA_BUS_FMT_RGB666_1X18 0x100948#define MEDIA_BUS_FMT_RGB666_1X18 0x1009
49#define MEDIA_BUS_FMT_RGB666_2X9_BE 0x1025
49#define MEDIA_BUS_FMT_BGR666_1X18 0x102350#define MEDIA_BUS_FMT_BGR666_1X18 0x1023
50#define MEDIA_BUS_FMT_RBG888_1X24 0x100e51#define MEDIA_BUS_FMT_RBG888_1X24 0x100e
51#define MEDIA_BUS_FMT_RGB666_1X24_CPADHI 0x101552#define MEDIA_BUS_FMT_RGB666_1X24_CPADHI 0x1015

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t