diff options
author | Dave Airlie <airlied@redhat.com> | 2017-12-07 17:15:54 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-12-07 17:15:54 -0500 |
commit | 5c379b4f4fd0c97e7bd31b3523c7e5c2bdf4a9b6 (patch) | |
tree | a3cef7f73bf671f011599f3309ee8e6870d27b95 | |
parent | 9c606cd4117a3c45e04a6616b1a0dbeb18eeee62 (diff) | |
parent | bc29489f712079378081e43d5b1b7470ed70184d (diff) |
Merge tag 'drm-misc-next-2017-12-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
UAPI Changes:
- Add "panel orientation" property to DRM to indicate orientation of the
panel vs the device's casing (Hans de Goede)
Core Changes:
- misc doc and bug fixes
Driver Changes:
- sun4i: Many improvements to the DE driver like multi-plane support and
YUV formats (Jernej Skrabec)
* tag 'drm-misc-next-2017-12-07' of git://anongit.freedesktop.org/drm/drm-misc: (50 commits)
drm/sun4i: Fix uninitialized variables in vi layer
drm/fb-helper: Fix potential NULL pointer dereference
gpu: drm: stm: Adopt SPDX identifiers
gpu: drm: sti: Adopt SPDX identifiers
drm/fsl-dcu: Use drm_mode_config_helper_suspend/resume()
drm/sun4i: Wire in DE2 YUV support
drm/sun4i: Expand DE2 scaler lib with YUV support
drm/sun4i: Add DE2 definitions for YUV formats
drm/sun4i: Add DE2 CSC library
drm/sun4i: Add CCSC property to DE2 configuration
drm/sun4i: Add support for HW scaling to DE2
drm/sun4i: Add scaler configuration to DE2 mixers
drm/sun4i: Add support for DE2 VI planes
drm/sun4i: Reorganize UI layer code in DE2
drm/sun4i: Add support for all HW supported DE2 RGB formats
drm/sun4i: Add multi plane support to DE2 driver
drm/sun4i: Move interlace related code in DE2
drm/sun4i: Move channel size related code in DE2
drm/sun4i: Move line width setting in DE2
drm/sun4i: Use values calculated by atomic check
...
89 files changed, 3661 insertions, 663 deletions
diff --git a/Documentation/devicetree/bindings/display/ilitek,ili9225.txt b/Documentation/devicetree/bindings/display/ilitek,ili9225.txt new file mode 100644 index 000000000000..21607a541c33 --- /dev/null +++ b/Documentation/devicetree/bindings/display/ilitek,ili9225.txt | |||
@@ -0,0 +1,25 @@ | |||
1 | Ilitek ILI9225 display panels | ||
2 | |||
3 | This binding is for display panels using an Ilitek ILI9225 controller in SPI | ||
4 | mode. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible: "ilitek,ili9225-2.2in-176x220" | ||
8 | - rs-gpios: Register select signal | ||
9 | - reset-gpios: Reset pin | ||
10 | |||
11 | The node for this driver must be a child node of a SPI controller, hence | ||
12 | all mandatory properties described in ../spi/spi-bus.txt must be specified. | ||
13 | |||
14 | Optional properties: | ||
15 | - rotation: panel rotation in degrees counter clockwise (0,90,180,270) | ||
16 | |||
17 | Example: | ||
18 | display@0{ | ||
19 | compatible = "ilitek,ili9225-2.2in-176x220"; | ||
20 | reg = <0>; | ||
21 | spi-max-frequency = <12000000>; | ||
22 | rs-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; | ||
23 | reset-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; | ||
24 | rotation = <270>; | ||
25 | }; | ||
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 0994bdd82cd3..41cb1ff07150 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
@@ -154,6 +154,7 @@ i2se I2SE GmbH | |||
154 | ibm International Business Machines (IBM) | 154 | ibm International Business Machines (IBM) |
155 | idt Integrated Device Technologies, Inc. | 155 | idt Integrated Device Technologies, Inc. |
156 | ifi Ingenieurburo Fur Ic-Technologie (I/F/I) | 156 | ifi Ingenieurburo Fur Ic-Technologie (I/F/I) |
157 | ilitek ILI Technology Corporation (ILITEK) | ||
157 | img Imagination Technologies Ltd. | 158 | img Imagination Technologies Ltd. |
158 | infineon Infineon Technologies | 159 | infineon Infineon Technologies |
159 | inforce Inforce Computing | 160 | inforce Inforce Computing |
diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index 13dd237418cc..3ea622876b67 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst | |||
@@ -163,6 +163,9 @@ Panel Helper Reference | |||
163 | .. kernel-doc:: drivers/gpu/drm/drm_panel.c | 163 | .. kernel-doc:: drivers/gpu/drm/drm_panel.c |
164 | :export: | 164 | :export: |
165 | 165 | ||
166 | .. kernel-doc:: drivers/gpu/drm/drm_panel_orientation_quirks.c | ||
167 | :export: | ||
168 | |||
166 | Display Port Helper Functions Reference | 169 | Display Port Helper Functions Reference |
167 | ======================================= | 170 | ======================================= |
168 | 171 | ||
diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 01eaa40dafc9..af614746d9c5 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst | |||
@@ -185,6 +185,15 @@ are better. | |||
185 | 185 | ||
186 | Contact: Sean Paul, Maintainer of the driver you plan to convert | 186 | Contact: Sean Paul, Maintainer of the driver you plan to convert |
187 | 187 | ||
188 | Convert drivers to use simple modeset suspend/resume | ||
189 | ---------------------------------------------------- | ||
190 | |||
191 | Most drivers (except i915 and nouveau) that use | ||
192 | drm_atomic_helper_suspend/resume() can probably be converted to use | ||
193 | drm_mode_config_helper_suspend/resume(). | ||
194 | |||
195 | Contact: Maintainer of the driver you plan to convert | ||
196 | |||
188 | Core refactorings | 197 | Core refactorings |
189 | ================= | 198 | ================= |
190 | 199 | ||
@@ -404,11 +413,6 @@ those drivers as simple as possible, so lots of room for refactoring: | |||
404 | a drm_device wrong. Doesn't matter, since everyone else gets it wrong | 413 | a drm_device wrong. Doesn't matter, since everyone else gets it wrong |
405 | too :-) | 414 | too :-) |
406 | 415 | ||
407 | - With the fbdev pointer in dev->mode_config we could also make | ||
408 | suspend/resume helpers entirely generic, at least if we add a | ||
409 | dev->mode_config.suspend_state. We could even provide a generic pm_ops | ||
410 | structure with those. | ||
411 | |||
412 | - also rework the drm_framebuffer_funcs->dirty hook wire-up, see above. | 416 | - also rework the drm_framebuffer_funcs->dirty hook wire-up, see above. |
413 | 417 | ||
414 | Contact: Noralf Trønnes, Daniel Vetter | 418 | Contact: Noralf Trønnes, Daniel Vetter |
diff --git a/MAINTAINERS b/MAINTAINERS index 069ba63190b2..8110df7acfea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4461,6 +4461,12 @@ T: git git://anongit.freedesktop.org/drm/drm-misc | |||
4461 | S: Maintained | 4461 | S: Maintained |
4462 | F: drivers/gpu/drm/tve200/ | 4462 | F: drivers/gpu/drm/tve200/ |
4463 | 4463 | ||
4464 | DRM DRIVER FOR ILITEK ILI9225 PANELS | ||
4465 | M: David Lechner <david@lechnology.com> | ||
4466 | S: Maintained | ||
4467 | F: drivers/gpu/drm/tinydrm/ili9225.c | ||
4468 | F: Documentation/devicetree/bindings/display/ili9225.txt | ||
4469 | |||
4464 | DRM DRIVER FOR INTEL I810 VIDEO CARDS | 4470 | DRM DRIVER FOR INTEL I810 VIDEO CARDS |
4465 | S: Orphan / Obsolete | 4471 | S: Orphan / Obsolete |
4466 | F: drivers/gpu/drm/i810/ | 4472 | F: drivers/gpu/drm/i810/ |
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 4d9f21831741..d853989848d6 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
@@ -7,6 +7,7 @@ | |||
7 | menuconfig DRM | 7 | menuconfig DRM |
8 | tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" | 8 | tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" |
9 | depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA | 9 | depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA |
10 | select DRM_PANEL_ORIENTATION_QUIRKS | ||
10 | select HDMI | 11 | select HDMI |
11 | select FB_CMDLINE | 12 | select FB_CMDLINE |
12 | select I2C | 13 | select I2C |
@@ -26,6 +27,10 @@ config DRM_MIPI_DSI | |||
26 | bool | 27 | bool |
27 | depends on DRM | 28 | depends on DRM |
28 | 29 | ||
30 | # Separate option because drm_panel_orientation_quirks.c is shared with fbdev | ||
31 | config DRM_PANEL_ORIENTATION_QUIRKS | ||
32 | tristate | ||
33 | |||
29 | config DRM_DP_AUX_CHARDEV | 34 | config DRM_DP_AUX_CHARDEV |
30 | bool "DRM DP AUX Interface" | 35 | bool "DRM DP AUX Interface" |
31 | depends on DRM | 36 | depends on DRM |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index e9500844333e..e5bf68b9c171 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
@@ -47,6 +47,7 @@ obj-$(CONFIG_DRM_DEBUG_MM_SELFTEST) += selftests/ | |||
47 | 47 | ||
48 | obj-$(CONFIG_DRM) += drm.o | 48 | obj-$(CONFIG_DRM) += drm.o |
49 | obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o | 49 | obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o |
50 | obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o | ||
50 | obj-$(CONFIG_DRM_ARM) += arm/ | 51 | obj-$(CONFIG_DRM_ARM) += arm/ |
51 | obj-$(CONFIG_DRM_TTM) += ttm/ | 52 | obj-$(CONFIG_DRM_TTM) += ttm/ |
52 | obj-$(CONFIG_DRM_TDFX) += tdfx/ | 53 | obj-$(CONFIG_DRM_TDFX) += tdfx/ |
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 91f2b0191368..e080e31a8513 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <drm/drm_fb_cma_helper.h> | 27 | #include <drm/drm_fb_cma_helper.h> |
28 | #include <drm/drm_gem_cma_helper.h> | 28 | #include <drm/drm_gem_cma_helper.h> |
29 | #include <drm/drm_gem_framebuffer_helper.h> | 29 | #include <drm/drm_gem_framebuffer_helper.h> |
30 | #include <drm/drm_modeset_helper.h> | ||
30 | #include <drm/drm_of.h> | 31 | #include <drm/drm_of.h> |
31 | 32 | ||
32 | #include "malidp_drv.h" | 33 | #include "malidp_drv.h" |
@@ -745,34 +746,15 @@ static int malidp_platform_remove(struct platform_device *pdev) | |||
745 | static int __maybe_unused malidp_pm_suspend(struct device *dev) | 746 | static int __maybe_unused malidp_pm_suspend(struct device *dev) |
746 | { | 747 | { |
747 | struct drm_device *drm = dev_get_drvdata(dev); | 748 | struct drm_device *drm = dev_get_drvdata(dev); |
748 | struct malidp_drm *malidp = drm->dev_private; | ||
749 | |||
750 | drm_kms_helper_poll_disable(drm); | ||
751 | console_lock(); | ||
752 | drm_fbdev_cma_set_suspend(malidp->fbdev, 1); | ||
753 | console_unlock(); | ||
754 | malidp->pm_state = drm_atomic_helper_suspend(drm); | ||
755 | if (IS_ERR(malidp->pm_state)) { | ||
756 | console_lock(); | ||
757 | drm_fbdev_cma_set_suspend(malidp->fbdev, 0); | ||
758 | console_unlock(); | ||
759 | drm_kms_helper_poll_enable(drm); | ||
760 | return PTR_ERR(malidp->pm_state); | ||
761 | } | ||
762 | 749 | ||
763 | return 0; | 750 | return drm_mode_config_helper_suspend(drm); |
764 | } | 751 | } |
765 | 752 | ||
766 | static int __maybe_unused malidp_pm_resume(struct device *dev) | 753 | static int __maybe_unused malidp_pm_resume(struct device *dev) |
767 | { | 754 | { |
768 | struct drm_device *drm = dev_get_drvdata(dev); | 755 | struct drm_device *drm = dev_get_drvdata(dev); |
769 | struct malidp_drm *malidp = drm->dev_private; | ||
770 | 756 | ||
771 | drm_atomic_helper_resume(drm, malidp->pm_state); | 757 | drm_mode_config_helper_resume(drm); |
772 | console_lock(); | ||
773 | drm_fbdev_cma_set_suspend(malidp->fbdev, 0); | ||
774 | console_unlock(); | ||
775 | drm_kms_helper_poll_enable(drm); | ||
776 | 758 | ||
777 | return 0; | 759 | return 0; |
778 | } | 760 | } |
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h index 2e2033140efc..70ed6aeccf05 100644 --- a/drivers/gpu/drm/arm/malidp_drv.h +++ b/drivers/gpu/drm/arm/malidp_drv.h | |||
@@ -24,7 +24,6 @@ struct malidp_drm { | |||
24 | struct drm_crtc crtc; | 24 | struct drm_crtc crtc; |
25 | wait_queue_head_t wq; | 25 | wait_queue_head_t wq; |
26 | atomic_t config_valid; | 26 | atomic_t config_valid; |
27 | struct drm_atomic_state *pm_state; | ||
28 | u32 core_id; | 27 | u32 core_id; |
29 | }; | 28 | }; |
30 | 29 | ||
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 25f4b2e9a44f..624edeb5c50d 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <drm/drm_connector.h> | 24 | #include <drm/drm_connector.h> |
25 | #include <drm/drm_edid.h> | 25 | #include <drm/drm_edid.h> |
26 | #include <drm/drm_encoder.h> | 26 | #include <drm/drm_encoder.h> |
27 | #include <drm/drm_utils.h> | ||
27 | 28 | ||
28 | #include "drm_crtc_internal.h" | 29 | #include "drm_crtc_internal.h" |
29 | #include "drm_internal.h" | 30 | #include "drm_internal.h" |
@@ -212,6 +213,8 @@ int drm_connector_init(struct drm_device *dev, | |||
212 | mutex_init(&connector->mutex); | 213 | mutex_init(&connector->mutex); |
213 | connector->edid_blob_ptr = NULL; | 214 | connector->edid_blob_ptr = NULL; |
214 | connector->status = connector_status_unknown; | 215 | connector->status = connector_status_unknown; |
216 | connector->display_info.panel_orientation = | ||
217 | DRM_MODE_PANEL_ORIENTATION_UNKNOWN; | ||
215 | 218 | ||
216 | drm_connector_get_cmdline_mode(connector); | 219 | drm_connector_get_cmdline_mode(connector); |
217 | 220 | ||
@@ -668,6 +671,13 @@ static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = { | |||
668 | { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" }, | 671 | { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" }, |
669 | }; | 672 | }; |
670 | 673 | ||
674 | static const struct drm_prop_enum_list drm_panel_orientation_enum_list[] = { | ||
675 | { DRM_MODE_PANEL_ORIENTATION_NORMAL, "Normal" }, | ||
676 | { DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP, "Upside Down" }, | ||
677 | { DRM_MODE_PANEL_ORIENTATION_LEFT_UP, "Left Side Up" }, | ||
678 | { DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, "Right Side Up" }, | ||
679 | }; | ||
680 | |||
671 | static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { | 681 | static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { |
672 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ | 682 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ |
673 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ | 683 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
@@ -776,6 +786,18 @@ DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, | |||
776 | * | 786 | * |
777 | * CRTC_ID: | 787 | * CRTC_ID: |
778 | * Mode object ID of the &drm_crtc this connector should be connected to. | 788 | * Mode object ID of the &drm_crtc this connector should be connected to. |
789 | * | ||
790 | * Connectors for LCD panels may also have one standardized property: | ||
791 | * | ||
792 | * panel orientation: | ||
793 | * On some devices the LCD panel is mounted in the casing in such a way | ||
794 | * that the up/top side of the panel does not match with the top side of | ||
795 | * the device. Userspace can use this property to check for this. | ||
796 | * Note that input coordinates from touchscreens (input devices with | ||
797 | * INPUT_PROP_DIRECT) will still map 1:1 to the actual LCD panel | ||
798 | * coordinates, so if userspace rotates the picture to adjust for | ||
799 | * the orientation it must also apply the same transformation to the | ||
800 | * touchscreen input coordinates. | ||
779 | */ | 801 | */ |
780 | 802 | ||
781 | int drm_connector_create_standard_properties(struct drm_device *dev) | 803 | int drm_connector_create_standard_properties(struct drm_device *dev) |
@@ -1251,6 +1273,57 @@ void drm_mode_connector_set_link_status_property(struct drm_connector *connector | |||
1251 | } | 1273 | } |
1252 | EXPORT_SYMBOL(drm_mode_connector_set_link_status_property); | 1274 | EXPORT_SYMBOL(drm_mode_connector_set_link_status_property); |
1253 | 1275 | ||
1276 | /** | ||
1277 | * drm_connector_init_panel_orientation_property - | ||
1278 | * initialize the connecters panel_orientation property | ||
1279 | * @connector: connector for which to init the panel-orientation property. | ||
1280 | * @width: width in pixels of the panel, used for panel quirk detection | ||
1281 | * @height: height in pixels of the panel, used for panel quirk detection | ||
1282 | * | ||
1283 | * This function should only be called for built-in panels, after setting | ||
1284 | * connector->display_info.panel_orientation first (if known). | ||
1285 | * | ||
1286 | * This function will check for platform specific (e.g. DMI based) quirks | ||
1287 | * overriding display_info.panel_orientation first, then if panel_orientation | ||
1288 | * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the | ||
1289 | * "panel orientation" property to the connector. | ||
1290 | * | ||
1291 | * Returns: | ||
1292 | * Zero on success, negative errno on failure. | ||
1293 | */ | ||
1294 | int drm_connector_init_panel_orientation_property( | ||
1295 | struct drm_connector *connector, int width, int height) | ||
1296 | { | ||
1297 | struct drm_device *dev = connector->dev; | ||
1298 | struct drm_display_info *info = &connector->display_info; | ||
1299 | struct drm_property *prop; | ||
1300 | int orientation_quirk; | ||
1301 | |||
1302 | orientation_quirk = drm_get_panel_orientation_quirk(width, height); | ||
1303 | if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) | ||
1304 | info->panel_orientation = orientation_quirk; | ||
1305 | |||
1306 | if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) | ||
1307 | return 0; | ||
1308 | |||
1309 | prop = dev->mode_config.panel_orientation_property; | ||
1310 | if (!prop) { | ||
1311 | prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, | ||
1312 | "panel orientation", | ||
1313 | drm_panel_orientation_enum_list, | ||
1314 | ARRAY_SIZE(drm_panel_orientation_enum_list)); | ||
1315 | if (!prop) | ||
1316 | return -ENOMEM; | ||
1317 | |||
1318 | dev->mode_config.panel_orientation_property = prop; | ||
1319 | } | ||
1320 | |||
1321 | drm_object_attach_property(&connector->base, prop, | ||
1322 | info->panel_orientation); | ||
1323 | return 0; | ||
1324 | } | ||
1325 | EXPORT_SYMBOL(drm_connector_init_panel_orientation_property); | ||
1326 | |||
1254 | int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, | 1327 | int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, |
1255 | struct drm_property *property, | 1328 | struct drm_property *property, |
1256 | uint64_t value) | 1329 | uint64_t value) |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 09919e8d67f9..04a3a5ce370a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <drm/drm_atomic.h> | 41 | #include <drm/drm_atomic.h> |
42 | #include <drm/drm_atomic_helper.h> | 42 | #include <drm/drm_atomic_helper.h> |
43 | 43 | ||
44 | #include "drm_crtc_internal.h" | ||
44 | #include "drm_crtc_helper_internal.h" | 45 | #include "drm_crtc_helper_internal.h" |
45 | 46 | ||
46 | static bool drm_fbdev_emulation = true; | 47 | static bool drm_fbdev_emulation = true; |
@@ -177,7 +178,7 @@ EXPORT_SYMBOL(drm_fb_helper_add_one_connector); | |||
177 | */ | 178 | */ |
178 | int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) | 179 | int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) |
179 | { | 180 | { |
180 | struct drm_device *dev = fb_helper->dev; | 181 | struct drm_device *dev; |
181 | struct drm_connector *connector; | 182 | struct drm_connector *connector; |
182 | struct drm_connector_list_iter conn_iter; | 183 | struct drm_connector_list_iter conn_iter; |
183 | int i, ret = 0; | 184 | int i, ret = 0; |
@@ -185,6 +186,8 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) | |||
185 | if (!drm_fbdev_emulation || !fb_helper) | 186 | if (!drm_fbdev_emulation || !fb_helper) |
186 | return 0; | 187 | return 0; |
187 | 188 | ||
189 | dev = fb_helper->dev; | ||
190 | |||
188 | mutex_lock(&fb_helper->lock); | 191 | mutex_lock(&fb_helper->lock); |
189 | drm_connector_list_iter_begin(dev, &conn_iter); | 192 | drm_connector_list_iter_begin(dev, &conn_iter); |
190 | drm_for_each_connector_iter(connector, &conn_iter) { | 193 | drm_for_each_connector_iter(connector, &conn_iter) { |
@@ -356,6 +359,7 @@ EXPORT_SYMBOL(drm_fb_helper_debug_leave); | |||
356 | static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active) | 359 | static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active) |
357 | { | 360 | { |
358 | struct drm_device *dev = fb_helper->dev; | 361 | struct drm_device *dev = fb_helper->dev; |
362 | struct drm_plane_state *plane_state; | ||
359 | struct drm_plane *plane; | 363 | struct drm_plane *plane; |
360 | struct drm_atomic_state *state; | 364 | struct drm_atomic_state *state; |
361 | int i, ret; | 365 | int i, ret; |
@@ -374,8 +378,6 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ | |||
374 | retry: | 378 | retry: |
375 | plane_mask = 0; | 379 | plane_mask = 0; |
376 | drm_for_each_plane(plane, dev) { | 380 | drm_for_each_plane(plane, dev) { |
377 | struct drm_plane_state *plane_state; | ||
378 | |||
379 | plane_state = drm_atomic_get_plane_state(state, plane); | 381 | plane_state = drm_atomic_get_plane_state(state, plane); |
380 | if (IS_ERR(plane_state)) { | 382 | if (IS_ERR(plane_state)) { |
381 | ret = PTR_ERR(plane_state); | 383 | ret = PTR_ERR(plane_state); |
@@ -398,6 +400,11 @@ retry: | |||
398 | 400 | ||
399 | for (i = 0; i < fb_helper->crtc_count; i++) { | 401 | for (i = 0; i < fb_helper->crtc_count; i++) { |
400 | struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; | 402 | struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; |
403 | struct drm_plane *primary = mode_set->crtc->primary; | ||
404 | |||
405 | /* Cannot fail as we've already gotten the plane state above */ | ||
406 | plane_state = drm_atomic_get_new_plane_state(state, primary); | ||
407 | plane_state->rotation = fb_helper->crtc_info[i].rotation; | ||
401 | 408 | ||
402 | ret = __drm_atomic_helper_set_config(mode_set, state); | 409 | ret = __drm_atomic_helper_set_config(mode_set, state); |
403 | if (ret != 0) | 410 | if (ret != 0) |
@@ -829,6 +836,7 @@ int drm_fb_helper_init(struct drm_device *dev, | |||
829 | if (!fb_helper->crtc_info[i].mode_set.connectors) | 836 | if (!fb_helper->crtc_info[i].mode_set.connectors) |
830 | goto out_free; | 837 | goto out_free; |
831 | fb_helper->crtc_info[i].mode_set.num_connectors = 0; | 838 | fb_helper->crtc_info[i].mode_set.num_connectors = 0; |
839 | fb_helper->crtc_info[i].rotation = DRM_MODE_ROTATE_0; | ||
832 | } | 840 | } |
833 | 841 | ||
834 | i = 0; | 842 | i = 0; |
@@ -2357,6 +2365,62 @@ out: | |||
2357 | return best_score; | 2365 | return best_score; |
2358 | } | 2366 | } |
2359 | 2367 | ||
2368 | /* | ||
2369 | * This function checks if rotation is necessary because of panel orientation | ||
2370 | * and if it is, if it is supported. | ||
2371 | * If rotation is necessary and supported, its gets set in fb_crtc.rotation. | ||
2372 | * If rotation is necessary but not supported, a DRM_MODE_ROTATE_* flag gets | ||
2373 | * or-ed into fb_helper->sw_rotations. In drm_setup_crtcs_fb() we check if only | ||
2374 | * one bit is set and then we set fb_info.fbcon_rotate_hint to make fbcon do | ||
2375 | * the unsupported rotation. | ||
2376 | */ | ||
2377 | static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper, | ||
2378 | struct drm_fb_helper_crtc *fb_crtc, | ||
2379 | struct drm_connector *connector) | ||
2380 | { | ||
2381 | struct drm_plane *plane = fb_crtc->mode_set.crtc->primary; | ||
2382 | uint64_t valid_mask = 0; | ||
2383 | int i, rotation; | ||
2384 | |||
2385 | fb_crtc->rotation = DRM_MODE_ROTATE_0; | ||
2386 | |||
2387 | switch (connector->display_info.panel_orientation) { | ||
2388 | case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: | ||
2389 | rotation = DRM_MODE_ROTATE_180; | ||
2390 | break; | ||
2391 | case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: | ||
2392 | rotation = DRM_MODE_ROTATE_90; | ||
2393 | break; | ||
2394 | case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: | ||
2395 | rotation = DRM_MODE_ROTATE_270; | ||
2396 | break; | ||
2397 | default: | ||
2398 | rotation = DRM_MODE_ROTATE_0; | ||
2399 | } | ||
2400 | |||
2401 | /* | ||
2402 | * TODO: support 90 / 270 degree hardware rotation, | ||
2403 | * depending on the hardware this may require the framebuffer | ||
2404 | * to be in a specific tiling format. | ||
2405 | */ | ||
2406 | if (rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) { | ||
2407 | fb_helper->sw_rotations |= rotation; | ||
2408 | return; | ||
2409 | } | ||
2410 | |||
2411 | for (i = 0; i < plane->rotation_property->num_values; i++) | ||
2412 | valid_mask |= (1ULL << plane->rotation_property->values[i]); | ||
2413 | |||
2414 | if (!(rotation & valid_mask)) { | ||
2415 | fb_helper->sw_rotations |= rotation; | ||
2416 | return; | ||
2417 | } | ||
2418 | |||
2419 | fb_crtc->rotation = rotation; | ||
2420 | /* Rotating in hardware, fbcon should not rotate */ | ||
2421 | fb_helper->sw_rotations |= DRM_MODE_ROTATE_0; | ||
2422 | } | ||
2423 | |||
2360 | static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, | 2424 | static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, |
2361 | u32 width, u32 height) | 2425 | u32 width, u32 height) |
2362 | { | 2426 | { |
@@ -2416,6 +2480,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, | |||
2416 | drm_fb_helper_modeset_release(fb_helper, | 2480 | drm_fb_helper_modeset_release(fb_helper, |
2417 | &fb_helper->crtc_info[i].mode_set); | 2481 | &fb_helper->crtc_info[i].mode_set); |
2418 | 2482 | ||
2483 | fb_helper->sw_rotations = 0; | ||
2419 | drm_fb_helper_for_each_connector(fb_helper, i) { | 2484 | drm_fb_helper_for_each_connector(fb_helper, i) { |
2420 | struct drm_display_mode *mode = modes[i]; | 2485 | struct drm_display_mode *mode = modes[i]; |
2421 | struct drm_fb_helper_crtc *fb_crtc = crtcs[i]; | 2486 | struct drm_fb_helper_crtc *fb_crtc = crtcs[i]; |
@@ -2435,6 +2500,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, | |||
2435 | modeset->mode = drm_mode_duplicate(dev, | 2500 | modeset->mode = drm_mode_duplicate(dev, |
2436 | fb_crtc->desired_mode); | 2501 | fb_crtc->desired_mode); |
2437 | drm_connector_get(connector); | 2502 | drm_connector_get(connector); |
2503 | drm_setup_crtc_rotation(fb_helper, fb_crtc, connector); | ||
2438 | modeset->connectors[modeset->num_connectors++] = connector; | 2504 | modeset->connectors[modeset->num_connectors++] = connector; |
2439 | modeset->x = offset->x; | 2505 | modeset->x = offset->x; |
2440 | modeset->y = offset->y; | 2506 | modeset->y = offset->y; |
@@ -2476,6 +2542,28 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) | |||
2476 | } | 2542 | } |
2477 | } | 2543 | } |
2478 | mutex_unlock(&fb_helper->dev->mode_config.mutex); | 2544 | mutex_unlock(&fb_helper->dev->mode_config.mutex); |
2545 | |||
2546 | switch (fb_helper->sw_rotations) { | ||
2547 | case DRM_MODE_ROTATE_0: | ||
2548 | info->fbcon_rotate_hint = FB_ROTATE_UR; | ||
2549 | break; | ||
2550 | case DRM_MODE_ROTATE_90: | ||
2551 | info->fbcon_rotate_hint = FB_ROTATE_CCW; | ||
2552 | break; | ||
2553 | case DRM_MODE_ROTATE_180: | ||
2554 | info->fbcon_rotate_hint = FB_ROTATE_UD; | ||
2555 | break; | ||
2556 | case DRM_MODE_ROTATE_270: | ||
2557 | info->fbcon_rotate_hint = FB_ROTATE_CW; | ||
2558 | break; | ||
2559 | default: | ||
2560 | /* | ||
2561 | * Multiple bits are set / multiple rotations requested | ||
2562 | * fbcon cannot handle separate rotation settings per | ||
2563 | * output, so fallback to unrotated. | ||
2564 | */ | ||
2565 | info->fbcon_rotate_hint = FB_ROTATE_UR; | ||
2566 | } | ||
2479 | } | 2567 | } |
2480 | 2568 | ||
2481 | /* Note: Drops fb_helper->lock before returning. */ | 2569 | /* Note: Drops fb_helper->lock before returning. */ |
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 9cb1eede0b4d..f1c24ab0ef09 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c | |||
@@ -20,6 +20,9 @@ | |||
20 | * OF THIS SOFTWARE. | 20 | * OF THIS SOFTWARE. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <drm/drm_atomic_helper.h> | ||
24 | #include <drm/drm_crtc_helper.h> | ||
25 | #include <drm/drm_fb_helper.h> | ||
23 | #include <drm/drm_modeset_helper.h> | 26 | #include <drm/drm_modeset_helper.h> |
24 | #include <drm/drm_plane_helper.h> | 27 | #include <drm/drm_plane_helper.h> |
25 | 28 | ||
@@ -156,3 +159,76 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | |||
156 | NULL); | 159 | NULL); |
157 | } | 160 | } |
158 | EXPORT_SYMBOL(drm_crtc_init); | 161 | EXPORT_SYMBOL(drm_crtc_init); |
162 | |||
163 | /** | ||
164 | * drm_mode_config_helper_suspend - Modeset suspend helper | ||
165 | * @dev: DRM device | ||
166 | * | ||
167 | * This helper function takes care of suspending the modeset side. It disables | ||
168 | * output polling if initialized, suspends fbdev if used and finally calls | ||
169 | * drm_atomic_helper_suspend(). | ||
170 | * If suspending fails, fbdev and polling is re-enabled. | ||
171 | * | ||
172 | * Returns: | ||
173 | * Zero on success, negative error code on error. | ||
174 | * | ||
175 | * See also: | ||
176 | * drm_kms_helper_poll_disable() and drm_fb_helper_set_suspend_unlocked(). | ||
177 | */ | ||
178 | int drm_mode_config_helper_suspend(struct drm_device *dev) | ||
179 | { | ||
180 | struct drm_atomic_state *state; | ||
181 | |||
182 | if (!dev) | ||
183 | return 0; | ||
184 | |||
185 | drm_kms_helper_poll_disable(dev); | ||
186 | drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1); | ||
187 | state = drm_atomic_helper_suspend(dev); | ||
188 | if (IS_ERR(state)) { | ||
189 | drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0); | ||
190 | drm_kms_helper_poll_enable(dev); | ||
191 | return PTR_ERR(state); | ||
192 | } | ||
193 | |||
194 | dev->mode_config.suspend_state = state; | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | EXPORT_SYMBOL(drm_mode_config_helper_suspend); | ||
199 | |||
200 | /** | ||
201 | * drm_mode_config_helper_resume - Modeset resume helper | ||
202 | * @dev: DRM device | ||
203 | * | ||
204 | * This helper function takes care of resuming the modeset side. It calls | ||
205 | * drm_atomic_helper_resume(), resumes fbdev if used and enables output polling | ||
206 | * if initiaized. | ||
207 | * | ||
208 | * Returns: | ||
209 | * Zero on success, negative error code on error. | ||
210 | * | ||
211 | * See also: | ||
212 | * drm_fb_helper_set_suspend_unlocked() and drm_kms_helper_poll_enable(). | ||
213 | */ | ||
214 | int drm_mode_config_helper_resume(struct drm_device *dev) | ||
215 | { | ||
216 | int ret; | ||
217 | |||
218 | if (!dev) | ||
219 | return 0; | ||
220 | |||
221 | if (WARN_ON(!dev->mode_config.suspend_state)) | ||
222 | return -EINVAL; | ||
223 | |||
224 | ret = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state); | ||
225 | if (ret) | ||
226 | DRM_ERROR("Failed to resume (%d)\n", ret); | ||
227 | dev->mode_config.suspend_state = NULL; | ||
228 | |||
229 | drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0); | ||
230 | drm_kms_helper_poll_enable(dev); | ||
231 | |||
232 | return ret; | ||
233 | } | ||
234 | EXPORT_SYMBOL(drm_mode_config_helper_resume); | ||
diff --git a/drivers/video/fbdev/core/fbcon_dmi_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 6904e47d1e51..901a4e9a87a3 100644 --- a/drivers/video/fbdev/core/fbcon_dmi_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c | |||
@@ -1,17 +1,17 @@ | |||
1 | /* SPDX-License-Identifier: MIT */ | ||
1 | /* | 2 | /* |
2 | * fbcon_dmi_quirks.c -- DMI based quirk detection for fbcon | 3 | * drm_panel_orientation_quirks.c -- Quirks for non-normal panel orientation |
3 | * | 4 | * |
4 | * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com> | 5 | * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com> |
5 | * | 6 | * |
6 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * Note the quirks in this file are shared with fbdev/efifb and as such |
7 | * License. See the file COPYING in the main directory of this archive for | 8 | * must not depend on other drm code. |
8 | * more details. | ||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/dmi.h> | 11 | #include <linux/dmi.h> |
12 | #include <linux/fb.h> | 12 | #include <drm/drm_connector.h> |
13 | #include <linux/kernel.h> | 13 | |
14 | #include "fbcon.h" | 14 | #ifdef CONFIG_DMI |
15 | 15 | ||
16 | /* | 16 | /* |
17 | * Some x86 clamshell design devices use portrait tablet screens and a display | 17 | * Some x86 clamshell design devices use portrait tablet screens and a display |
@@ -21,56 +21,56 @@ | |||
21 | * and a list of known BIOS dates to avoid false positives. | 21 | * and a list of known BIOS dates to avoid false positives. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | struct fbcon_dmi_rotate_data { | 24 | struct drm_dmi_panel_orientation_data { |
25 | int width; | 25 | int width; |
26 | int height; | 26 | int height; |
27 | const char * const *bios_dates; | 27 | const char * const *bios_dates; |
28 | int rotate; | 28 | int orientation; |
29 | }; | 29 | }; |
30 | 30 | ||
31 | static const struct fbcon_dmi_rotate_data rotate_data_asus_t100ha = { | 31 | static const struct drm_dmi_panel_orientation_data asus_t100ha = { |
32 | .width = 800, | 32 | .width = 800, |
33 | .height = 1280, | 33 | .height = 1280, |
34 | .rotate = FB_ROTATE_CCW, | 34 | .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | static const struct fbcon_dmi_rotate_data rotate_data_gpd_pocket = { | 37 | static const struct drm_dmi_panel_orientation_data gpd_pocket = { |
38 | .width = 1200, | 38 | .width = 1200, |
39 | .height = 1920, | 39 | .height = 1920, |
40 | .bios_dates = (const char * const []){ "05/26/2017", "06/28/2017", | 40 | .bios_dates = (const char * const []){ "05/26/2017", "06/28/2017", |
41 | "07/05/2017", "08/07/2017", NULL }, | 41 | "07/05/2017", "08/07/2017", NULL }, |
42 | .rotate = FB_ROTATE_CW, | 42 | .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, |
43 | }; | 43 | }; |
44 | 44 | ||
45 | static const struct fbcon_dmi_rotate_data rotate_data_gpd_win = { | 45 | static const struct drm_dmi_panel_orientation_data gpd_win = { |
46 | .width = 720, | 46 | .width = 720, |
47 | .height = 1280, | 47 | .height = 1280, |
48 | .bios_dates = (const char * const []){ | 48 | .bios_dates = (const char * const []){ |
49 | "10/25/2016", "11/18/2016", "12/23/2016", "12/26/2016", | 49 | "10/25/2016", "11/18/2016", "12/23/2016", "12/26/2016", |
50 | "02/21/2017", "03/20/2017", "05/25/2017", NULL }, | 50 | "02/21/2017", "03/20/2017", "05/25/2017", NULL }, |
51 | .rotate = FB_ROTATE_CW, | 51 | .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static const struct fbcon_dmi_rotate_data rotate_data_itworks_tw891 = { | 54 | static const struct drm_dmi_panel_orientation_data itworks_tw891 = { |
55 | .width = 800, | 55 | .width = 800, |
56 | .height = 1280, | 56 | .height = 1280, |
57 | .bios_dates = (const char * const []){ "10/16/2015", NULL }, | 57 | .bios_dates = (const char * const []){ "10/16/2015", NULL }, |
58 | .rotate = FB_ROTATE_CW, | 58 | .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, |
59 | }; | 59 | }; |
60 | 60 | ||
61 | static const struct fbcon_dmi_rotate_data rotate_data_vios_lth17 = { | 61 | static const struct drm_dmi_panel_orientation_data vios_lth17 = { |
62 | .width = 800, | 62 | .width = 800, |
63 | .height = 1280, | 63 | .height = 1280, |
64 | .rotate = FB_ROTATE_CW, | 64 | .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, |
65 | }; | 65 | }; |
66 | 66 | ||
67 | static const struct dmi_system_id rotate_data[] = { | 67 | static const struct dmi_system_id orientation_data[] = { |
68 | { /* Asus T100HA */ | 68 | { /* Asus T100HA */ |
69 | .matches = { | 69 | .matches = { |
70 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 70 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
71 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100HAN"), | 71 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100HAN"), |
72 | }, | 72 | }, |
73 | .driver_data = (void *)&rotate_data_asus_t100ha, | 73 | .driver_data = (void *)&asus_t100ha, |
74 | }, { /* | 74 | }, { /* |
75 | * GPD Pocket, note that the the DMI data is less generic then | 75 | * GPD Pocket, note that the the DMI data is less generic then |
76 | * it seems, devices with a board-vendor of "AMI Corporation" | 76 | * it seems, devices with a board-vendor of "AMI Corporation" |
@@ -83,7 +83,7 @@ static const struct dmi_system_id rotate_data[] = { | |||
83 | DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"), | 83 | DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"), |
84 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"), | 84 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"), |
85 | }, | 85 | }, |
86 | .driver_data = (void *)&rotate_data_gpd_pocket, | 86 | .driver_data = (void *)&gpd_pocket, |
87 | }, { /* GPD Win (same note on DMI match as GPD Pocket) */ | 87 | }, { /* GPD Win (same note on DMI match as GPD Pocket) */ |
88 | .matches = { | 88 | .matches = { |
89 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), | 89 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), |
@@ -91,7 +91,7 @@ static const struct dmi_system_id rotate_data[] = { | |||
91 | DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"), | 91 | DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"), |
92 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"), | 92 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"), |
93 | }, | 93 | }, |
94 | .driver_data = (void *)&rotate_data_gpd_win, | 94 | .driver_data = (void *)&gpd_win, |
95 | }, { /* I.T.Works TW891 */ | 95 | }, { /* I.T.Works TW891 */ |
96 | .matches = { | 96 | .matches = { |
97 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."), | 97 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."), |
@@ -99,37 +99,54 @@ static const struct dmi_system_id rotate_data[] = { | |||
99 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), | 99 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), |
100 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"), | 100 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"), |
101 | }, | 101 | }, |
102 | .driver_data = (void *)&rotate_data_itworks_tw891, | 102 | .driver_data = (void *)&itworks_tw891, |
103 | }, { /* VIOS LTH17 */ | 103 | }, { /* VIOS LTH17 */ |
104 | .matches = { | 104 | .matches = { |
105 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"), | 105 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"), |
106 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"), | 106 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"), |
107 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "VIOS"), | ||
108 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "LTH17"), | ||
109 | }, | 107 | }, |
110 | .driver_data = (void *)&rotate_data_vios_lth17, | 108 | .driver_data = (void *)&vios_lth17, |
111 | }, | 109 | }, |
112 | {} | 110 | {} |
113 | }; | 111 | }; |
114 | 112 | ||
115 | int fbcon_platform_get_rotate(struct fb_info *info) | 113 | /** |
114 | * drm_get_panel_orientation_quirk - Check for panel orientation quirks | ||
115 | * @width: width in pixels of the panel | ||
116 | * @height: height in pixels of the panel | ||
117 | * | ||
118 | * This function checks for platform specific (e.g. DMI based) quirks | ||
119 | * providing info on panel_orientation for systems where this cannot be | ||
120 | * probed from the hard-/firm-ware. To avoid false-positive this function | ||
121 | * takes the panel resolution as argument and checks that against the | ||
122 | * resolution expected by the quirk-table entry. | ||
123 | * | ||
124 | * Note this function is also used outside of the drm-subsys, by for example | ||
125 | * the efifb code. Because of this this function gets compiled into its own | ||
126 | * kernel-module when built as a module. | ||
127 | * | ||
128 | * Returns: | ||
129 | * A DRM_MODE_PANEL_ORIENTATION_* value if there is a quirk for this system, | ||
130 | * or DRM_MODE_PANEL_ORIENTATION_UNKNOWN if there is no quirk. | ||
131 | */ | ||
132 | int drm_get_panel_orientation_quirk(int width, int height) | ||
116 | { | 133 | { |
117 | const struct dmi_system_id *match; | 134 | const struct dmi_system_id *match; |
118 | const struct fbcon_dmi_rotate_data *data; | 135 | const struct drm_dmi_panel_orientation_data *data; |
119 | const char *bios_date; | 136 | const char *bios_date; |
120 | int i; | 137 | int i; |
121 | 138 | ||
122 | for (match = dmi_first_match(rotate_data); | 139 | for (match = dmi_first_match(orientation_data); |
123 | match; | 140 | match; |
124 | match = dmi_first_match(match + 1)) { | 141 | match = dmi_first_match(match + 1)) { |
125 | data = match->driver_data; | 142 | data = match->driver_data; |
126 | 143 | ||
127 | if (data->width != info->var.xres || | 144 | if (data->width != width || |
128 | data->height != info->var.yres) | 145 | data->height != height) |
129 | continue; | 146 | continue; |
130 | 147 | ||
131 | if (!data->bios_dates) | 148 | if (!data->bios_dates) |
132 | return data->rotate; | 149 | return data->orientation; |
133 | 150 | ||
134 | bios_date = dmi_get_system_info(DMI_BIOS_DATE); | 151 | bios_date = dmi_get_system_info(DMI_BIOS_DATE); |
135 | if (!bios_date) | 152 | if (!bios_date) |
@@ -137,9 +154,21 @@ int fbcon_platform_get_rotate(struct fb_info *info) | |||
137 | 154 | ||
138 | for (i = 0; data->bios_dates[i]; i++) { | 155 | for (i = 0; data->bios_dates[i]; i++) { |
139 | if (!strcmp(data->bios_dates[i], bios_date)) | 156 | if (!strcmp(data->bios_dates[i], bios_date)) |
140 | return data->rotate; | 157 | return data->orientation; |
141 | } | 158 | } |
142 | } | 159 | } |
143 | 160 | ||
144 | return FB_ROTATE_UR; | 161 | return DRM_MODE_PANEL_ORIENTATION_UNKNOWN; |
145 | } | 162 | } |
163 | EXPORT_SYMBOL(drm_get_panel_orientation_quirk); | ||
164 | |||
165 | #else | ||
166 | |||
167 | /* There are no quirks for non x86 devices yet */ | ||
168 | int drm_get_panel_orientation_quirk(int width, int height) | ||
169 | { | ||
170 | return DRM_MODE_PANEL_ORIENTATION_UNKNOWN; | ||
171 | } | ||
172 | EXPORT_SYMBOL(drm_get_panel_orientation_quirk); | ||
173 | |||
174 | #endif | ||
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 8de93a226c24..9a17725b0f7a 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c | |||
@@ -218,8 +218,9 @@ static void drm_gem_map_detach(struct dma_buf *dma_buf, | |||
218 | sgt = prime_attach->sgt; | 218 | sgt = prime_attach->sgt; |
219 | if (sgt) { | 219 | if (sgt) { |
220 | if (prime_attach->dir != DMA_NONE) | 220 | if (prime_attach->dir != DMA_NONE) |
221 | dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, | 221 | dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, |
222 | prime_attach->dir); | 222 | prime_attach->dir, |
223 | DMA_ATTR_SKIP_CPU_SYNC); | ||
223 | sg_free_table(sgt); | 224 | sg_free_table(sgt); |
224 | } | 225 | } |
225 | 226 | ||
@@ -277,7 +278,8 @@ static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach, | |||
277 | sgt = obj->dev->driver->gem_prime_get_sg_table(obj); | 278 | sgt = obj->dev->driver->gem_prime_get_sg_table(obj); |
278 | 279 | ||
279 | if (!IS_ERR(sgt)) { | 280 | if (!IS_ERR(sgt)) { |
280 | if (!dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir)) { | 281 | if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir, |
282 | DMA_ATTR_SKIP_CPU_SYNC)) { | ||
281 | sg_free_table(sgt); | 283 | sg_free_table(sgt); |
282 | kfree(sgt); | 284 | kfree(sgt); |
283 | sgt = ERR_PTR(-ENOMEM); | 285 | sgt = ERR_PTR(-ENOMEM); |
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 6dc2dde5b672..555fbe54d6e2 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c | |||
@@ -216,8 +216,7 @@ enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector, | |||
216 | * suspend/resume. | 216 | * suspend/resume. |
217 | * | 217 | * |
218 | * Drivers can call this helper from their device resume implementation. It is | 218 | * Drivers can call this helper from their device resume implementation. It is |
219 | * an error to call this when the output polling support has not yet been set | 219 | * not an error to call this even when output polling isn't enabled. |
220 | * up. | ||
221 | * | 220 | * |
222 | * Note that calls to enable and disable polling must be strictly ordered, which | 221 | * Note that calls to enable and disable polling must be strictly ordered, which |
223 | * is automatically the case when they're only call from suspend/resume | 222 | * is automatically the case when they're only call from suspend/resume |
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index faf17b83b910..80232321a244 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <drm/drm_crtc_helper.h> | 27 | #include <drm/drm_crtc_helper.h> |
28 | #include <drm/drm_fb_cma_helper.h> | 28 | #include <drm/drm_fb_cma_helper.h> |
29 | #include <drm/drm_gem_cma_helper.h> | 29 | #include <drm/drm_gem_cma_helper.h> |
30 | #include <drm/drm_modeset_helper.h> | ||
30 | 31 | ||
31 | #include "fsl_dcu_drm_crtc.h" | 32 | #include "fsl_dcu_drm_crtc.h" |
32 | #include "fsl_dcu_drm_drv.h" | 33 | #include "fsl_dcu_drm_drv.h" |
@@ -188,26 +189,17 @@ static struct drm_driver fsl_dcu_drm_driver = { | |||
188 | static int fsl_dcu_drm_pm_suspend(struct device *dev) | 189 | static int fsl_dcu_drm_pm_suspend(struct device *dev) |
189 | { | 190 | { |
190 | struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev); | 191 | struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev); |
192 | int ret; | ||
191 | 193 | ||
192 | if (!fsl_dev) | 194 | if (!fsl_dev) |
193 | return 0; | 195 | return 0; |
194 | 196 | ||
195 | disable_irq(fsl_dev->irq); | 197 | disable_irq(fsl_dev->irq); |
196 | drm_kms_helper_poll_disable(fsl_dev->drm); | ||
197 | |||
198 | console_lock(); | ||
199 | drm_fbdev_cma_set_suspend(fsl_dev->fbdev, 1); | ||
200 | console_unlock(); | ||
201 | |||
202 | fsl_dev->state = drm_atomic_helper_suspend(fsl_dev->drm); | ||
203 | if (IS_ERR(fsl_dev->state)) { | ||
204 | console_lock(); | ||
205 | drm_fbdev_cma_set_suspend(fsl_dev->fbdev, 0); | ||
206 | console_unlock(); | ||
207 | 198 | ||
208 | drm_kms_helper_poll_enable(fsl_dev->drm); | 199 | ret = drm_mode_config_helper_suspend(fsl_dev->drm); |
200 | if (ret) { | ||
209 | enable_irq(fsl_dev->irq); | 201 | enable_irq(fsl_dev->irq); |
210 | return PTR_ERR(fsl_dev->state); | 202 | return ret; |
211 | } | 203 | } |
212 | 204 | ||
213 | clk_disable_unprepare(fsl_dev->clk); | 205 | clk_disable_unprepare(fsl_dev->clk); |
@@ -233,13 +225,8 @@ static int fsl_dcu_drm_pm_resume(struct device *dev) | |||
233 | fsl_tcon_bypass_enable(fsl_dev->tcon); | 225 | fsl_tcon_bypass_enable(fsl_dev->tcon); |
234 | fsl_dcu_drm_init_planes(fsl_dev->drm); | 226 | fsl_dcu_drm_init_planes(fsl_dev->drm); |
235 | enable_irq(fsl_dev->irq); | 227 | enable_irq(fsl_dev->irq); |
236 | drm_atomic_helper_resume(fsl_dev->drm, fsl_dev->state); | ||
237 | |||
238 | console_lock(); | ||
239 | drm_fbdev_cma_set_suspend(fsl_dev->fbdev, 0); | ||
240 | console_unlock(); | ||
241 | 228 | ||
242 | drm_kms_helper_poll_enable(fsl_dev->drm); | 229 | drm_mode_config_helper_resume(fsl_dev->drm); |
243 | 230 | ||
244 | return 0; | 231 | return 0; |
245 | } | 232 | } |
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h index da9bfd432ca6..93bfb98012d4 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h | |||
@@ -196,7 +196,6 @@ struct fsl_dcu_drm_device { | |||
196 | struct drm_encoder encoder; | 196 | struct drm_encoder encoder; |
197 | struct fsl_dcu_drm_connector connector; | 197 | struct fsl_dcu_drm_connector connector; |
198 | const struct fsl_dcu_soc_data *soc; | 198 | const struct fsl_dcu_soc_data *soc; |
199 | struct drm_atomic_state *state; | ||
200 | }; | 199 | }; |
201 | 200 | ||
202 | int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev); | 201 | int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev); |
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index f09474b0c4d3..1b60df3c14a0 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c | |||
@@ -1666,6 +1666,27 @@ static const struct drm_connector_funcs intel_dsi_connector_funcs = { | |||
1666 | .atomic_duplicate_state = intel_digital_connector_duplicate_state, | 1666 | .atomic_duplicate_state = intel_digital_connector_duplicate_state, |
1667 | }; | 1667 | }; |
1668 | 1668 | ||
1669 | static int intel_dsi_get_panel_orientation(struct intel_connector *connector) | ||
1670 | { | ||
1671 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); | ||
1672 | int orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; | ||
1673 | enum plane plane; | ||
1674 | u32 val; | ||
1675 | |||
1676 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { | ||
1677 | if (connector->encoder->crtc_mask == BIT(PIPE_B)) | ||
1678 | plane = PLANE_B; | ||
1679 | else | ||
1680 | plane = PLANE_A; | ||
1681 | |||
1682 | val = I915_READ(DSPCNTR(plane)); | ||
1683 | if (val & DISPPLANE_ROTATE_180) | ||
1684 | orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; | ||
1685 | } | ||
1686 | |||
1687 | return orientation; | ||
1688 | } | ||
1689 | |||
1669 | static void intel_dsi_add_properties(struct intel_connector *connector) | 1690 | static void intel_dsi_add_properties(struct intel_connector *connector) |
1670 | { | 1691 | { |
1671 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); | 1692 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
@@ -1681,6 +1702,13 @@ static void intel_dsi_add_properties(struct intel_connector *connector) | |||
1681 | allowed_scalers); | 1702 | allowed_scalers); |
1682 | 1703 | ||
1683 | connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT; | 1704 | connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT; |
1705 | |||
1706 | connector->base.display_info.panel_orientation = | ||
1707 | intel_dsi_get_panel_orientation(connector); | ||
1708 | drm_connector_init_panel_orientation_property( | ||
1709 | &connector->base, | ||
1710 | connector->panel.fixed_mode->hdisplay, | ||
1711 | connector->panel.fixed_mode->vdisplay); | ||
1684 | } | 1712 | } |
1685 | } | 1713 | } |
1686 | 1714 | ||
diff --git a/drivers/gpu/drm/sti/sti_awg_utils.c b/drivers/gpu/drm/sti/sti_awg_utils.c index 2da7d6866d5d..7c5a7830b6e8 100644 --- a/drivers/gpu/drm/sti/sti_awg_utils.c +++ b/drivers/gpu/drm/sti/sti_awg_utils.c | |||
@@ -1,7 +1,7 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. | 4 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "sti_awg_utils.h" | 7 | #include "sti_awg_utils.h" |
diff --git a/drivers/gpu/drm/sti/sti_awg_utils.h b/drivers/gpu/drm/sti/sti_awg_utils.h index 45d599bd570a..258a568f050b 100644 --- a/drivers/gpu/drm/sti/sti_awg_utils.h +++ b/drivers/gpu/drm/sti/sti_awg_utils.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. | 4 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #ifndef _STI_AWG_UTILS_H_ | 7 | #ifndef _STI_AWG_UTILS_H_ |
diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c index 6e4bf68262db..021b8fcaa0b9 100644 --- a/drivers/gpu/drm/sti/sti_compositor.c +++ b/drivers/gpu/drm/sti/sti_compositor.c | |||
@@ -1,9 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | 4 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> |
4 | * Fabien Dessenne <fabien.dessenne@st.com> | 5 | * Fabien Dessenne <fabien.dessenne@st.com> |
5 | * for STMicroelectronics. | 6 | * for STMicroelectronics. |
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/component.h> | 9 | #include <linux/component.h> |
diff --git a/drivers/gpu/drm/sti/sti_compositor.h b/drivers/gpu/drm/sti/sti_compositor.h index 2952a2d25a52..ac4bb3834810 100644 --- a/drivers/gpu/drm/sti/sti_compositor.h +++ b/drivers/gpu/drm/sti/sti_compositor.h | |||
@@ -1,9 +1,9 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | 4 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> |
4 | * Fabien Dessenne <fabien.dessenne@st.com> | 5 | * Fabien Dessenne <fabien.dessenne@st.com> |
5 | * for STMicroelectronics. | 6 | * for STMicroelectronics. |
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifndef _STI_COMPOSITOR_H_ | 9 | #ifndef _STI_COMPOSITOR_H_ |
diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c index e8a4d48e985a..21e50d7b1f86 100644 --- a/drivers/gpu/drm/sti/sti_crtc.c +++ b/drivers/gpu/drm/sti/sti_crtc.c | |||
@@ -1,9 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | 4 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> |
4 | * Fabien Dessenne <fabien.dessenne@st.com> | 5 | * Fabien Dessenne <fabien.dessenne@st.com> |
5 | * for STMicroelectronics. | 6 | * for STMicroelectronics. |
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
diff --git a/drivers/gpu/drm/sti/sti_crtc.h b/drivers/gpu/drm/sti/sti_crtc.h index 3f2d89a3634d..d87c488212d6 100644 --- a/drivers/gpu/drm/sti/sti_crtc.h +++ b/drivers/gpu/drm/sti/sti_crtc.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. | 4 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #ifndef _STI_CRTC_H_ | 7 | #ifndef _STI_CRTC_H_ |
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c index b709ebbec095..df0a282b9615 100644 --- a/drivers/gpu/drm/sti/sti_cursor.c +++ b/drivers/gpu/drm/sti/sti_cursor.c | |||
@@ -1,9 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Vincent Abriou <vincent.abriou@st.com> | 4 | * Authors: Vincent Abriou <vincent.abriou@st.com> |
4 | * Fabien Dessenne <fabien.dessenne@st.com> | 5 | * Fabien Dessenne <fabien.dessenne@st.com> |
5 | * for STMicroelectronics. | 6 | * for STMicroelectronics. |
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/seq_file.h> | 9 | #include <linux/seq_file.h> |
diff --git a/drivers/gpu/drm/sti/sti_cursor.h b/drivers/gpu/drm/sti/sti_cursor.h index 2ee5c10e8b33..067feda5226c 100644 --- a/drivers/gpu/drm/sti/sti_cursor.h +++ b/drivers/gpu/drm/sti/sti_cursor.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2013 | 3 | * Copyright (C) STMicroelectronics SA 2013 |
3 | * Authors: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. | 4 | * Authors: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #ifndef _STI_CURSOR_H_ | 7 | #ifndef _STI_CURSOR_H_ |
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 9e9343101738..88d1dc6408af 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c | |||
@@ -1,7 +1,7 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. | 4 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <drm/drmP.h> | 7 | #include <drm/drmP.h> |
diff --git a/drivers/gpu/drm/sti/sti_drv.h b/drivers/gpu/drm/sti/sti_drv.h index 6502ed2d3351..abc49b43566e 100644 --- a/drivers/gpu/drm/sti/sti_drv.h +++ b/drivers/gpu/drm/sti/sti_drv.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. | 4 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #ifndef _STI_DRV_H_ | 7 | #ifndef _STI_DRV_H_ |
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index 83314aee65cb..a5979cd25cc7 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c | |||
@@ -1,7 +1,7 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. | 4 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/clk.h> | 7 | #include <linux/clk.h> |
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index b65eea4f2c97..9b2c47051b51 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c | |||
@@ -1,9 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | 4 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> |
4 | * Fabien Dessenne <fabien.dessenne@st.com> | 5 | * Fabien Dessenne <fabien.dessenne@st.com> |
5 | * for STMicroelectronics. | 6 | * for STMicroelectronics. |
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | 7 | */ |
8 | #include <linux/seq_file.h> | 8 | #include <linux/seq_file.h> |
9 | 9 | ||
diff --git a/drivers/gpu/drm/sti/sti_gdp.h b/drivers/gpu/drm/sti/sti_gdp.h index 73947a4a8004..d3e8ebfe2e66 100644 --- a/drivers/gpu/drm/sti/sti_gdp.h +++ b/drivers/gpu/drm/sti/sti_gdp.h | |||
@@ -1,9 +1,9 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | 4 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> |
4 | * Fabien Dessenne <fabien.dessenne@st.com> | 5 | * Fabien Dessenne <fabien.dessenne@st.com> |
5 | * for STMicroelectronics. | 6 | * for STMicroelectronics. |
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifndef _STI_GDP_H_ | 9 | #ifndef _STI_GDP_H_ |
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c index cf65e32b5090..67bbdb49fffc 100644 --- a/drivers/gpu/drm/sti/sti_hda.c +++ b/drivers/gpu/drm/sti/sti_hda.c | |||
@@ -1,7 +1,7 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. | 4 | * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/clk.h> | 7 | #include <linux/clk.h> |
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 4ea1cc1c032e..58f431102512 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c | |||
@@ -1,7 +1,7 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. | 4 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/clk.h> | 7 | #include <linux/clk.h> |
diff --git a/drivers/gpu/drm/sti/sti_hdmi.h b/drivers/gpu/drm/sti/sti_hdmi.h index c6469b56ce7e..63a24941db3b 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.h +++ b/drivers/gpu/drm/sti/sti_hdmi.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. | 4 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #ifndef _STI_HDMI_H_ | 7 | #ifndef _STI_HDMI_H_ |
diff --git a/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c b/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c index 8e0ceb0ced33..01699af6a768 100644 --- a/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c +++ b/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c | |||
@@ -1,7 +1,7 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. | 4 | * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "sti_hdmi_tx3g4c28phy.h" | 7 | #include "sti_hdmi_tx3g4c28phy.h" |
diff --git a/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h b/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h index f99a7ff281ef..d261947ef30a 100644 --- a/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h +++ b/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. | 4 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #ifndef _STI_HDMI_TX3G4C28PHY_H_ | 7 | #ifndef _STI_HDMI_TX3G4C28PHY_H_ |
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index b19b3430b296..106be8c4e58b 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c | |||
@@ -1,7 +1,7 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. | 4 | * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/component.h> | 7 | #include <linux/component.h> |
diff --git a/drivers/gpu/drm/sti/sti_hqvdp_lut.h b/drivers/gpu/drm/sti/sti_hqvdp_lut.h index 619af7f4384e..57cccd9546a3 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp_lut.h +++ b/drivers/gpu/drm/sti/sti_hqvdp_lut.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. | 4 | * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #ifndef _STI_HQVDP_LUT_H_ | 7 | #ifndef _STI_HQVDP_LUT_H_ |
diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c index 2bd1d46fe1cd..a4f45c74d678 100644 --- a/drivers/gpu/drm/sti/sti_mixer.c +++ b/drivers/gpu/drm/sti/sti_mixer.c | |||
@@ -1,9 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | 4 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> |
4 | * Fabien Dessenne <fabien.dessenne@st.com> | 5 | * Fabien Dessenne <fabien.dessenne@st.com> |
5 | * for STMicroelectronics. | 6 | * for STMicroelectronics. |
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | 7 | */ |
8 | #include <linux/seq_file.h> | 8 | #include <linux/seq_file.h> |
9 | 9 | ||
diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h index e64a00e61049..4cb3cfddc03a 100644 --- a/drivers/gpu/drm/sti/sti_mixer.h +++ b/drivers/gpu/drm/sti/sti_mixer.h | |||
@@ -1,9 +1,9 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | 4 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> |
4 | * Fabien Dessenne <fabien.dessenne@st.com> | 5 | * Fabien Dessenne <fabien.dessenne@st.com> |
5 | * for STMicroelectronics. | 6 | * for STMicroelectronics. |
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifndef _STI_MIXER_H_ | 9 | #ifndef _STI_MIXER_H_ |
diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c index 427d8f58c6b1..b074609c960a 100644 --- a/drivers/gpu/drm/sti/sti_plane.c +++ b/drivers/gpu/drm/sti/sti_plane.c | |||
@@ -1,9 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | 4 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> |
4 | * Fabien Dessenne <fabien.dessenne@st.com> | 5 | * Fabien Dessenne <fabien.dessenne@st.com> |
5 | * for STMicroelectronics. | 6 | * for STMicroelectronics. |
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <drm/drmP.h> | 9 | #include <drm/drmP.h> |
diff --git a/drivers/gpu/drm/sti/sti_plane.h b/drivers/gpu/drm/sti/sti_plane.h index c36c13faaa18..b8d7fae2a014 100644 --- a/drivers/gpu/drm/sti/sti_plane.h +++ b/drivers/gpu/drm/sti/sti_plane.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. | 4 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #ifndef _STI_PLANE_H_ | 7 | #ifndef _STI_PLANE_H_ |
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c index 8959fcc743a8..ea4a3b87fa55 100644 --- a/drivers/gpu/drm/sti/sti_tvout.c +++ b/drivers/gpu/drm/sti/sti_tvout.c | |||
@@ -1,9 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | 4 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> |
4 | * Vincent Abriou <vincent.abriou@st.com> | 5 | * Vincent Abriou <vincent.abriou@st.com> |
5 | * for STMicroelectronics. | 6 | * for STMicroelectronics. |
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
diff --git a/drivers/gpu/drm/sti/sti_vid.c b/drivers/gpu/drm/sti/sti_vid.c index 577a3341d3c1..2aac36c95835 100644 --- a/drivers/gpu/drm/sti/sti_vid.c +++ b/drivers/gpu/drm/sti/sti_vid.c | |||
@@ -1,7 +1,7 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. | 4 | * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | #include <linux/seq_file.h> | 6 | #include <linux/seq_file.h> |
7 | 7 | ||
diff --git a/drivers/gpu/drm/sti/sti_vid.h b/drivers/gpu/drm/sti/sti_vid.h index fdc90f922a05..9dbd78461de1 100644 --- a/drivers/gpu/drm/sti/sti_vid.h +++ b/drivers/gpu/drm/sti/sti_vid.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. | 4 | * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #ifndef _STI_VID_H_ | 7 | #ifndef _STI_VID_H_ |
diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c index 3aa2fa6f2228..6c421644de18 100644 --- a/drivers/gpu/drm/sti/sti_vtg.c +++ b/drivers/gpu/drm/sti/sti_vtg.c | |||
@@ -1,10 +1,10 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | 4 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> |
4 | * Fabien Dessenne <fabien.dessenne@st.com> | 5 | * Fabien Dessenne <fabien.dessenne@st.com> |
5 | * Vincent Abriou <vincent.abriou@st.com> | 6 | * Vincent Abriou <vincent.abriou@st.com> |
6 | * for STMicroelectronics. | 7 | * for STMicroelectronics. |
7 | * License terms: GNU General Public License (GPL), version 2 | ||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
diff --git a/drivers/gpu/drm/sti/sti_vtg.h b/drivers/gpu/drm/sti/sti_vtg.h index f1dcdf9c2342..d177129e5bcb 100644 --- a/drivers/gpu/drm/sti/sti_vtg.h +++ b/drivers/gpu/drm/sti/sti_vtg.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | 3 | * Copyright (C) STMicroelectronics SA 2014 |
3 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. | 4 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics. |
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #ifndef _STI_VTG_H_ | 7 | #ifndef _STI_VTG_H_ |
diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c index c857663eafc2..2d6e9ca0450b 100644 --- a/drivers/gpu/drm/stm/drv.c +++ b/drivers/gpu/drm/stm/drv.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2017 | 3 | * Copyright (C) STMicroelectronics SA 2017 |
3 | * | 4 | * |
@@ -5,8 +6,6 @@ | |||
5 | * Yannick Fertre <yannick.fertre@st.com> | 6 | * Yannick Fertre <yannick.fertre@st.com> |
6 | * Fabien Dessenne <fabien.dessenne@st.com> | 7 | * Fabien Dessenne <fabien.dessenne@st.com> |
7 | * Mickael Reulier <mickael.reulier@st.com> | 8 | * Mickael Reulier <mickael.reulier@st.com> |
8 | * | ||
9 | * License terms: GNU General Public License (GPL), version 2 | ||
10 | */ | 9 | */ |
11 | 10 | ||
12 | #include <linux/component.h> | 11 | #include <linux/component.h> |
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c index 3e8b9ed7e8b3..82dcb20cdaa3 100644 --- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c +++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | |||
@@ -1,10 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2017 | 3 | * Copyright (C) STMicroelectronics SA 2017 |
3 | * | 4 | * |
4 | * Authors: Philippe Cornu <philippe.cornu@st.com> | 5 | * Authors: Philippe Cornu <philippe.cornu@st.com> |
5 | * Yannick Fertre <yannick.fertre@st.com> | 6 | * Yannick Fertre <yannick.fertre@st.com> |
6 | * | ||
7 | * License terms: GNU General Public License (GPL), version 2 | ||
8 | */ | 7 | */ |
9 | 8 | ||
10 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 35e884239f60..394613b0fd46 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2017 | 3 | * Copyright (C) STMicroelectronics SA 2017 |
3 | * | 4 | * |
@@ -5,8 +6,6 @@ | |||
5 | * Yannick Fertre <yannick.fertre@st.com> | 6 | * Yannick Fertre <yannick.fertre@st.com> |
6 | * Fabien Dessenne <fabien.dessenne@st.com> | 7 | * Fabien Dessenne <fabien.dessenne@st.com> |
7 | * Mickael Reulier <mickael.reulier@st.com> | 8 | * Mickael Reulier <mickael.reulier@st.com> |
8 | * | ||
9 | * License terms: GNU General Public License (GPL), version 2 | ||
10 | */ | 9 | */ |
11 | 10 | ||
12 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h index ae437557d715..d5da74d24995 100644 --- a/drivers/gpu/drm/stm/ltdc.h +++ b/drivers/gpu/drm/stm/ltdc.h | |||
@@ -1,3 +1,4 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Copyright (C) STMicroelectronics SA 2017 | 3 | * Copyright (C) STMicroelectronics SA 2017 |
3 | * | 4 | * |
@@ -5,8 +6,6 @@ | |||
5 | * Yannick Fertre <yannick.fertre@st.com> | 6 | * Yannick Fertre <yannick.fertre@st.com> |
6 | * Fabien Dessenne <fabien.dessenne@st.com> | 7 | * Fabien Dessenne <fabien.dessenne@st.com> |
7 | * Mickael Reulier <mickael.reulier@st.com> | 8 | * Mickael Reulier <mickael.reulier@st.com> |
8 | * | ||
9 | * License terms: GNU General Public License (GPL), version 2 | ||
10 | */ | 9 | */ |
11 | 10 | ||
12 | #ifndef _LTDC_H_ | 11 | #ifndef _LTDC_H_ |
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index 0c2f8c7facae..82a6ac57fbe3 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile | |||
@@ -9,7 +9,9 @@ sun4i-drm-hdmi-y += sun4i_hdmi_enc.o | |||
9 | sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o | 9 | sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o |
10 | sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o | 10 | sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o |
11 | 11 | ||
12 | sun8i-mixer-y += sun8i_mixer.o sun8i_layer.o | 12 | sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ |
13 | sun8i_vi_layer.o sun8i_ui_scaler.o \ | ||
14 | sun8i_vi_scaler.o sun8i_csc.o | ||
13 | 15 | ||
14 | sun4i-tcon-y += sun4i_crtc.o | 16 | sun4i-tcon-y += sun4i_crtc.o |
15 | sun4i-tcon-y += sun4i_dotclock.o | 17 | sun4i-tcon-y += sun4i_dotclock.o |
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 75c76cdd82bc..49215d91c853 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c | |||
@@ -187,13 +187,7 @@ static bool sun4i_drv_node_is_frontend(struct device_node *node) | |||
187 | 187 | ||
188 | static bool sun4i_drv_node_is_tcon(struct device_node *node) | 188 | static bool sun4i_drv_node_is_tcon(struct device_node *node) |
189 | { | 189 | { |
190 | return of_device_is_compatible(node, "allwinner,sun4i-a10-tcon") || | 190 | return !!of_match_node(sun4i_tcon_of_table, node); |
191 | of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") || | ||
192 | of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") || | ||
193 | of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") || | ||
194 | of_device_is_compatible(node, "allwinner,sun7i-a20-tcon") || | ||
195 | of_device_is_compatible(node, "allwinner,sun8i-a33-tcon") || | ||
196 | of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon"); | ||
197 | } | 191 | } |
198 | 192 | ||
199 | static int compare_of(struct device *dev, void *data) | 193 | static int compare_of(struct device *dev, void *data) |
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index e122f5b2a395..a1ed462c2430 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c | |||
@@ -900,7 +900,8 @@ static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { | |||
900 | /* nothing is supported */ | 900 | /* nothing is supported */ |
901 | }; | 901 | }; |
902 | 902 | ||
903 | static const struct of_device_id sun4i_tcon_of_table[] = { | 903 | /* sun4i_drv uses this list to check if a device node is a TCON */ |
904 | const struct of_device_id sun4i_tcon_of_table[] = { | ||
904 | { .compatible = "allwinner,sun4i-a10-tcon", .data = &sun4i_a10_quirks }, | 905 | { .compatible = "allwinner,sun4i-a10-tcon", .data = &sun4i_a10_quirks }, |
905 | { .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks }, | 906 | { .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks }, |
906 | { .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks }, | 907 | { .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks }, |
@@ -911,6 +912,7 @@ static const struct of_device_id sun4i_tcon_of_table[] = { | |||
911 | { } | 912 | { } |
912 | }; | 913 | }; |
913 | MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table); | 914 | MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table); |
915 | EXPORT_SYMBOL(sun4i_tcon_of_table); | ||
914 | 916 | ||
915 | static struct platform_driver sun4i_tcon_platform_driver = { | 917 | static struct platform_driver sun4i_tcon_platform_driver = { |
916 | .probe = sun4i_tcon_probe, | 918 | .probe = sun4i_tcon_probe, |
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index f61bf6d83b4a..839266a38505 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h | |||
@@ -197,4 +197,6 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon, | |||
197 | void sun4i_tcon_set_status(struct sun4i_tcon *crtc, | 197 | void sun4i_tcon_set_status(struct sun4i_tcon *crtc, |
198 | const struct drm_encoder *encoder, bool enable); | 198 | const struct drm_encoder *encoder, bool enable); |
199 | 199 | ||
200 | extern const struct of_device_id sun4i_tcon_of_table[]; | ||
201 | |||
200 | #endif /* __SUN4I_TCON_H__ */ | 202 | #endif /* __SUN4I_TCON_H__ */ |
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c new file mode 100644 index 000000000000..b14925b40ccf --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_csc.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation; either version 2 of | ||
7 | * the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <drm/drmP.h> | ||
11 | |||
12 | #include "sun8i_csc.h" | ||
13 | #include "sun8i_mixer.h" | ||
14 | |||
15 | static const u32 ccsc_base[2][2] = { | ||
16 | {CCSC00_OFFSET, CCSC01_OFFSET}, | ||
17 | {CCSC10_OFFSET, CCSC11_OFFSET}, | ||
18 | }; | ||
19 | |||
20 | /* | ||
21 | * Factors are in two's complement format, 10 bits for fractinal part. | ||
22 | * First tree values in each line are multiplication factor and last | ||
23 | * value is constant, which is added at the end. | ||
24 | */ | ||
25 | static const u32 yuv2rgb[] = { | ||
26 | 0x000004A8, 0x00000000, 0x00000662, 0xFFFC845A, | ||
27 | 0x000004A8, 0xFFFFFE6F, 0xFFFFFCBF, 0x00021DF4, | ||
28 | 0x000004A8, 0x00000813, 0x00000000, 0xFFFBAC4A, | ||
29 | }; | ||
30 | |||
31 | static const u32 yvu2rgb[] = { | ||
32 | 0x000004A8, 0x00000662, 0x00000000, 0xFFFC845A, | ||
33 | 0x000004A8, 0xFFFFFCBF, 0xFFFFFE6F, 0x00021DF4, | ||
34 | 0x000004A8, 0x00000000, 0x00000813, 0xFFFBAC4A, | ||
35 | }; | ||
36 | |||
37 | static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, | ||
38 | enum sun8i_csc_mode mode) | ||
39 | { | ||
40 | const u32 *table; | ||
41 | int i, data; | ||
42 | |||
43 | switch (mode) { | ||
44 | case SUN8I_CSC_MODE_YUV2RGB: | ||
45 | table = yuv2rgb; | ||
46 | break; | ||
47 | case SUN8I_CSC_MODE_YVU2RGB: | ||
48 | table = yvu2rgb; | ||
49 | break; | ||
50 | default: | ||
51 | DRM_WARN("Wrong CSC mode specified.\n"); | ||
52 | return; | ||
53 | } | ||
54 | |||
55 | for (i = 0; i < 12; i++) { | ||
56 | data = table[i]; | ||
57 | /* For some reason, 0x200 must be added to constant parts */ | ||
58 | if (((i + 1) & 3) == 0) | ||
59 | data += 0x200; | ||
60 | regmap_write(map, SUN8I_CSC_COEFF(base, i), data); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | static void sun8i_csc_enable(struct regmap *map, u32 base, bool enable) | ||
65 | { | ||
66 | u32 val; | ||
67 | |||
68 | if (enable) | ||
69 | val = SUN8I_CSC_CTRL_EN; | ||
70 | else | ||
71 | val = 0; | ||
72 | |||
73 | regmap_update_bits(map, SUN8I_CSC_CTRL(base), SUN8I_CSC_CTRL_EN, val); | ||
74 | } | ||
75 | |||
76 | void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, | ||
77 | enum sun8i_csc_mode mode) | ||
78 | { | ||
79 | u32 base; | ||
80 | |||
81 | base = ccsc_base[mixer->cfg->ccsc][layer]; | ||
82 | |||
83 | sun8i_csc_set_coefficients(mixer->engine.regs, base, mode); | ||
84 | } | ||
85 | |||
86 | void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable) | ||
87 | { | ||
88 | u32 base; | ||
89 | |||
90 | base = ccsc_base[mixer->cfg->ccsc][layer]; | ||
91 | |||
92 | sun8i_csc_enable(mixer->engine.regs, base, enable); | ||
93 | } | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h new file mode 100644 index 000000000000..880e8fbb0855 --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_csc.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation; either version 2 of | ||
7 | * the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #ifndef _SUN8I_CSC_H_ | ||
11 | #define _SUN8I_CSC_H_ | ||
12 | |||
13 | struct sun8i_mixer; | ||
14 | |||
15 | /* VI channel CSC units offsets */ | ||
16 | #define CCSC00_OFFSET 0xAA050 | ||
17 | #define CCSC01_OFFSET 0xFA000 | ||
18 | #define CCSC10_OFFSET 0xA0000 | ||
19 | #define CCSC11_OFFSET 0xF0000 | ||
20 | |||
21 | #define SUN8I_CSC_CTRL(base) (base + 0x0) | ||
22 | #define SUN8I_CSC_COEFF(base, i) (base + 0x10 + 4 * i) | ||
23 | |||
24 | #define SUN8I_CSC_CTRL_EN BIT(0) | ||
25 | |||
26 | enum sun8i_csc_mode { | ||
27 | SUN8I_CSC_MODE_OFF, | ||
28 | SUN8I_CSC_MODE_YUV2RGB, | ||
29 | SUN8I_CSC_MODE_YVU2RGB, | ||
30 | }; | ||
31 | |||
32 | void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, | ||
33 | enum sun8i_csc_mode mode); | ||
34 | void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable); | ||
35 | |||
36 | #endif | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c deleted file mode 100644 index 23810ff72684..000000000000 --- a/drivers/gpu/drm/sun4i/sun8i_layer.c +++ /dev/null | |||
@@ -1,134 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) Icenowy Zheng <icenowy@aosc.io> | ||
3 | * | ||
4 | * Based on sun4i_layer.h, which is: | ||
5 | * Copyright (C) 2015 Free Electrons | ||
6 | * Copyright (C) 2015 NextThing Co | ||
7 | * | ||
8 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation; either version 2 of | ||
13 | * the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <drm/drm_atomic_helper.h> | ||
17 | #include <drm/drm_plane_helper.h> | ||
18 | #include <drm/drmP.h> | ||
19 | |||
20 | #include "sun8i_layer.h" | ||
21 | #include "sun8i_mixer.h" | ||
22 | |||
23 | struct sun8i_plane_desc { | ||
24 | enum drm_plane_type type; | ||
25 | const uint32_t *formats; | ||
26 | uint32_t nformats; | ||
27 | }; | ||
28 | |||
29 | static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane, | ||
30 | struct drm_plane_state *old_state) | ||
31 | { | ||
32 | struct sun8i_layer *layer = plane_to_sun8i_layer(plane); | ||
33 | struct sun8i_mixer *mixer = layer->mixer; | ||
34 | |||
35 | sun8i_mixer_layer_enable(mixer, layer->id, false); | ||
36 | } | ||
37 | |||
38 | static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane, | ||
39 | struct drm_plane_state *old_state) | ||
40 | { | ||
41 | struct sun8i_layer *layer = plane_to_sun8i_layer(plane); | ||
42 | struct sun8i_mixer *mixer = layer->mixer; | ||
43 | |||
44 | sun8i_mixer_update_layer_coord(mixer, layer->id, plane); | ||
45 | sun8i_mixer_update_layer_formats(mixer, layer->id, plane); | ||
46 | sun8i_mixer_update_layer_buffer(mixer, layer->id, plane); | ||
47 | sun8i_mixer_layer_enable(mixer, layer->id, true); | ||
48 | } | ||
49 | |||
50 | static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = { | ||
51 | .atomic_disable = sun8i_mixer_layer_atomic_disable, | ||
52 | .atomic_update = sun8i_mixer_layer_atomic_update, | ||
53 | }; | ||
54 | |||
55 | static const struct drm_plane_funcs sun8i_mixer_layer_funcs = { | ||
56 | .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, | ||
57 | .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, | ||
58 | .destroy = drm_plane_cleanup, | ||
59 | .disable_plane = drm_atomic_helper_disable_plane, | ||
60 | .reset = drm_atomic_helper_plane_reset, | ||
61 | .update_plane = drm_atomic_helper_update_plane, | ||
62 | }; | ||
63 | |||
64 | static const uint32_t sun8i_mixer_layer_formats[] = { | ||
65 | DRM_FORMAT_RGB888, | ||
66 | DRM_FORMAT_ARGB8888, | ||
67 | DRM_FORMAT_XRGB8888, | ||
68 | }; | ||
69 | |||
70 | static const struct sun8i_plane_desc sun8i_mixer_planes[] = { | ||
71 | { | ||
72 | .type = DRM_PLANE_TYPE_PRIMARY, | ||
73 | .formats = sun8i_mixer_layer_formats, | ||
74 | .nformats = ARRAY_SIZE(sun8i_mixer_layer_formats), | ||
75 | }, | ||
76 | }; | ||
77 | |||
78 | static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm, | ||
79 | struct sun8i_mixer *mixer, | ||
80 | const struct sun8i_plane_desc *plane) | ||
81 | { | ||
82 | struct sun8i_layer *layer; | ||
83 | int ret; | ||
84 | |||
85 | layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL); | ||
86 | if (!layer) | ||
87 | return ERR_PTR(-ENOMEM); | ||
88 | |||
89 | /* possible crtcs are set later */ | ||
90 | ret = drm_universal_plane_init(drm, &layer->plane, 0, | ||
91 | &sun8i_mixer_layer_funcs, | ||
92 | plane->formats, plane->nformats, | ||
93 | NULL, plane->type, NULL); | ||
94 | if (ret) { | ||
95 | dev_err(drm->dev, "Couldn't initialize layer\n"); | ||
96 | return ERR_PTR(ret); | ||
97 | } | ||
98 | |||
99 | drm_plane_helper_add(&layer->plane, | ||
100 | &sun8i_mixer_layer_helper_funcs); | ||
101 | layer->mixer = mixer; | ||
102 | |||
103 | return layer; | ||
104 | } | ||
105 | |||
106 | struct drm_plane **sun8i_layers_init(struct drm_device *drm, | ||
107 | struct sunxi_engine *engine) | ||
108 | { | ||
109 | struct drm_plane **planes; | ||
110 | struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); | ||
111 | int i; | ||
112 | |||
113 | planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1, | ||
114 | sizeof(*planes), GFP_KERNEL); | ||
115 | if (!planes) | ||
116 | return ERR_PTR(-ENOMEM); | ||
117 | |||
118 | for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) { | ||
119 | const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i]; | ||
120 | struct sun8i_layer *layer; | ||
121 | |||
122 | layer = sun8i_layer_init_one(drm, mixer, plane); | ||
123 | if (IS_ERR(layer)) { | ||
124 | dev_err(drm->dev, "Couldn't initialize %s plane\n", | ||
125 | i ? "overlay" : "primary"); | ||
126 | return ERR_CAST(layer); | ||
127 | }; | ||
128 | |||
129 | layer->id = i; | ||
130 | planes[i] = &layer->plane; | ||
131 | }; | ||
132 | |||
133 | return planes; | ||
134 | } | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h b/drivers/gpu/drm/sun4i/sun8i_layer.h deleted file mode 100644 index e5eccd27cff0..000000000000 --- a/drivers/gpu/drm/sun4i/sun8i_layer.h +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) Icenowy Zheng <icenowy@aosc.io> | ||
3 | * | ||
4 | * Based on sun4i_layer.h, which is: | ||
5 | * Copyright (C) 2015 Free Electrons | ||
6 | * Copyright (C) 2015 NextThing Co | ||
7 | * | ||
8 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation; either version 2 of | ||
13 | * the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifndef _SUN8I_LAYER_H_ | ||
17 | #define _SUN8I_LAYER_H_ | ||
18 | |||
19 | struct sunxi_engine; | ||
20 | |||
21 | struct sun8i_layer { | ||
22 | struct drm_plane plane; | ||
23 | struct sun4i_drv *drv; | ||
24 | struct sun8i_mixer *mixer; | ||
25 | int id; | ||
26 | }; | ||
27 | |||
28 | static inline struct sun8i_layer * | ||
29 | plane_to_sun8i_layer(struct drm_plane *plane) | ||
30 | { | ||
31 | return container_of(plane, struct sun8i_layer, plane); | ||
32 | } | ||
33 | |||
34 | struct drm_plane **sun8i_layers_init(struct drm_device *drm, | ||
35 | struct sunxi_engine *engine); | ||
36 | #endif /* _SUN8I_LAYER_H_ */ | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index cb193c5f1686..29ceeb016d72 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c | |||
@@ -26,204 +26,288 @@ | |||
26 | 26 | ||
27 | #include "sun4i_drv.h" | 27 | #include "sun4i_drv.h" |
28 | #include "sun8i_mixer.h" | 28 | #include "sun8i_mixer.h" |
29 | #include "sun8i_layer.h" | 29 | #include "sun8i_ui_layer.h" |
30 | #include "sun8i_vi_layer.h" | ||
30 | #include "sunxi_engine.h" | 31 | #include "sunxi_engine.h" |
31 | 32 | ||
32 | static void sun8i_mixer_commit(struct sunxi_engine *engine) | 33 | static const struct de2_fmt_info de2_formats[] = { |
33 | { | 34 | { |
34 | DRM_DEBUG_DRIVER("Committing changes\n"); | 35 | .drm_fmt = DRM_FORMAT_ARGB8888, |
35 | 36 | .de2_fmt = SUN8I_MIXER_FBFMT_ARGB8888, | |
36 | regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF, | 37 | .rgb = true, |
37 | SUN8I_MIXER_GLOBAL_DBUFF_ENABLE); | 38 | .csc = SUN8I_CSC_MODE_OFF, |
38 | } | 39 | }, |
39 | 40 | { | |
40 | void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, | 41 | .drm_fmt = DRM_FORMAT_ABGR8888, |
41 | int layer, bool enable) | 42 | .de2_fmt = SUN8I_MIXER_FBFMT_ABGR8888, |
42 | { | 43 | .rgb = true, |
43 | u32 val; | 44 | .csc = SUN8I_CSC_MODE_OFF, |
44 | /* Currently the first UI channel is used */ | 45 | }, |
45 | int chan = mixer->cfg->vi_num; | 46 | { |
46 | 47 | .drm_fmt = DRM_FORMAT_RGBA8888, | |
47 | DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", layer, chan); | 48 | .de2_fmt = SUN8I_MIXER_FBFMT_RGBA8888, |
48 | 49 | .rgb = true, | |
49 | if (enable) | 50 | .csc = SUN8I_CSC_MODE_OFF, |
50 | val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN; | 51 | }, |
51 | else | 52 | { |
52 | val = 0; | 53 | .drm_fmt = DRM_FORMAT_BGRA8888, |
53 | 54 | .de2_fmt = SUN8I_MIXER_FBFMT_BGRA8888, | |
54 | regmap_update_bits(mixer->engine.regs, | 55 | .rgb = true, |
55 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer), | 56 | .csc = SUN8I_CSC_MODE_OFF, |
56 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val); | 57 | }, |
57 | 58 | { | |
58 | /* Set the alpha configuration */ | 59 | .drm_fmt = DRM_FORMAT_XRGB8888, |
59 | regmap_update_bits(mixer->engine.regs, | 60 | .de2_fmt = SUN8I_MIXER_FBFMT_XRGB8888, |
60 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer), | 61 | .rgb = true, |
61 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK, | 62 | .csc = SUN8I_CSC_MODE_OFF, |
62 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF); | 63 | }, |
63 | regmap_update_bits(mixer->engine.regs, | 64 | { |
64 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer), | 65 | .drm_fmt = DRM_FORMAT_XBGR8888, |
65 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK, | 66 | .de2_fmt = SUN8I_MIXER_FBFMT_XBGR8888, |
66 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF); | 67 | .rgb = true, |
67 | } | 68 | .csc = SUN8I_CSC_MODE_OFF, |
68 | 69 | }, | |
69 | static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane, | 70 | { |
70 | u32 format, u32 *mode) | 71 | .drm_fmt = DRM_FORMAT_RGBX8888, |
71 | { | 72 | .de2_fmt = SUN8I_MIXER_FBFMT_RGBX8888, |
72 | switch (format) { | 73 | .rgb = true, |
73 | case DRM_FORMAT_ARGB8888: | 74 | .csc = SUN8I_CSC_MODE_OFF, |
74 | *mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888; | 75 | }, |
75 | break; | 76 | { |
76 | 77 | .drm_fmt = DRM_FORMAT_BGRX8888, | |
77 | case DRM_FORMAT_XRGB8888: | 78 | .de2_fmt = SUN8I_MIXER_FBFMT_BGRX8888, |
78 | *mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888; | 79 | .rgb = true, |
79 | break; | 80 | .csc = SUN8I_CSC_MODE_OFF, |
80 | 81 | }, | |
81 | case DRM_FORMAT_RGB888: | 82 | { |
82 | *mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888; | 83 | .drm_fmt = DRM_FORMAT_RGB888, |
83 | break; | 84 | .de2_fmt = SUN8I_MIXER_FBFMT_RGB888, |
84 | 85 | .rgb = true, | |
85 | default: | 86 | .csc = SUN8I_CSC_MODE_OFF, |
86 | return -EINVAL; | 87 | }, |
87 | } | 88 | { |
88 | 89 | .drm_fmt = DRM_FORMAT_BGR888, | |
89 | return 0; | 90 | .de2_fmt = SUN8I_MIXER_FBFMT_BGR888, |
90 | } | 91 | .rgb = true, |
92 | .csc = SUN8I_CSC_MODE_OFF, | ||
93 | }, | ||
94 | { | ||
95 | .drm_fmt = DRM_FORMAT_RGB565, | ||
96 | .de2_fmt = SUN8I_MIXER_FBFMT_RGB565, | ||
97 | .rgb = true, | ||
98 | .csc = SUN8I_CSC_MODE_OFF, | ||
99 | }, | ||
100 | { | ||
101 | .drm_fmt = DRM_FORMAT_BGR565, | ||
102 | .de2_fmt = SUN8I_MIXER_FBFMT_BGR565, | ||
103 | .rgb = true, | ||
104 | .csc = SUN8I_CSC_MODE_OFF, | ||
105 | }, | ||
106 | { | ||
107 | .drm_fmt = DRM_FORMAT_ARGB4444, | ||
108 | .de2_fmt = SUN8I_MIXER_FBFMT_ARGB4444, | ||
109 | .rgb = true, | ||
110 | .csc = SUN8I_CSC_MODE_OFF, | ||
111 | }, | ||
112 | { | ||
113 | .drm_fmt = DRM_FORMAT_ABGR4444, | ||
114 | .de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444, | ||
115 | .rgb = true, | ||
116 | .csc = SUN8I_CSC_MODE_OFF, | ||
117 | }, | ||
118 | { | ||
119 | .drm_fmt = DRM_FORMAT_RGBA4444, | ||
120 | .de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444, | ||
121 | .rgb = true, | ||
122 | .csc = SUN8I_CSC_MODE_OFF, | ||
123 | }, | ||
124 | { | ||
125 | .drm_fmt = DRM_FORMAT_BGRA4444, | ||
126 | .de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444, | ||
127 | .rgb = true, | ||
128 | .csc = SUN8I_CSC_MODE_OFF, | ||
129 | }, | ||
130 | { | ||
131 | .drm_fmt = DRM_FORMAT_ARGB1555, | ||
132 | .de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555, | ||
133 | .rgb = true, | ||
134 | .csc = SUN8I_CSC_MODE_OFF, | ||
135 | }, | ||
136 | { | ||
137 | .drm_fmt = DRM_FORMAT_ABGR1555, | ||
138 | .de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555, | ||
139 | .rgb = true, | ||
140 | .csc = SUN8I_CSC_MODE_OFF, | ||
141 | }, | ||
142 | { | ||
143 | .drm_fmt = DRM_FORMAT_RGBA5551, | ||
144 | .de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551, | ||
145 | .rgb = true, | ||
146 | .csc = SUN8I_CSC_MODE_OFF, | ||
147 | }, | ||
148 | { | ||
149 | .drm_fmt = DRM_FORMAT_BGRA5551, | ||
150 | .de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551, | ||
151 | .rgb = true, | ||
152 | .csc = SUN8I_CSC_MODE_OFF, | ||
153 | }, | ||
154 | { | ||
155 | .drm_fmt = DRM_FORMAT_UYVY, | ||
156 | .de2_fmt = SUN8I_MIXER_FBFMT_UYVY, | ||
157 | .rgb = false, | ||
158 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
159 | }, | ||
160 | { | ||
161 | .drm_fmt = DRM_FORMAT_VYUY, | ||
162 | .de2_fmt = SUN8I_MIXER_FBFMT_VYUY, | ||
163 | .rgb = false, | ||
164 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
165 | }, | ||
166 | { | ||
167 | .drm_fmt = DRM_FORMAT_YUYV, | ||
168 | .de2_fmt = SUN8I_MIXER_FBFMT_YUYV, | ||
169 | .rgb = false, | ||
170 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
171 | }, | ||
172 | { | ||
173 | .drm_fmt = DRM_FORMAT_YVYU, | ||
174 | .de2_fmt = SUN8I_MIXER_FBFMT_YVYU, | ||
175 | .rgb = false, | ||
176 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
177 | }, | ||
178 | { | ||
179 | .drm_fmt = DRM_FORMAT_NV16, | ||
180 | .de2_fmt = SUN8I_MIXER_FBFMT_NV16, | ||
181 | .rgb = false, | ||
182 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
183 | }, | ||
184 | { | ||
185 | .drm_fmt = DRM_FORMAT_NV61, | ||
186 | .de2_fmt = SUN8I_MIXER_FBFMT_NV61, | ||
187 | .rgb = false, | ||
188 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
189 | }, | ||
190 | { | ||
191 | .drm_fmt = DRM_FORMAT_NV12, | ||
192 | .de2_fmt = SUN8I_MIXER_FBFMT_NV12, | ||
193 | .rgb = false, | ||
194 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
195 | }, | ||
196 | { | ||
197 | .drm_fmt = DRM_FORMAT_NV21, | ||
198 | .de2_fmt = SUN8I_MIXER_FBFMT_NV21, | ||
199 | .rgb = false, | ||
200 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
201 | }, | ||
202 | { | ||
203 | .drm_fmt = DRM_FORMAT_YUV444, | ||
204 | .de2_fmt = SUN8I_MIXER_FBFMT_RGB888, | ||
205 | .rgb = true, | ||
206 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
207 | }, | ||
208 | { | ||
209 | .drm_fmt = DRM_FORMAT_YUV422, | ||
210 | .de2_fmt = SUN8I_MIXER_FBFMT_YUV422, | ||
211 | .rgb = false, | ||
212 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
213 | }, | ||
214 | { | ||
215 | .drm_fmt = DRM_FORMAT_YUV420, | ||
216 | .de2_fmt = SUN8I_MIXER_FBFMT_YUV420, | ||
217 | .rgb = false, | ||
218 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
219 | }, | ||
220 | { | ||
221 | .drm_fmt = DRM_FORMAT_YUV411, | ||
222 | .de2_fmt = SUN8I_MIXER_FBFMT_YUV411, | ||
223 | .rgb = false, | ||
224 | .csc = SUN8I_CSC_MODE_YUV2RGB, | ||
225 | }, | ||
226 | { | ||
227 | .drm_fmt = DRM_FORMAT_YVU444, | ||
228 | .de2_fmt = SUN8I_MIXER_FBFMT_RGB888, | ||
229 | .rgb = true, | ||
230 | .csc = SUN8I_CSC_MODE_YVU2RGB, | ||
231 | }, | ||
232 | { | ||
233 | .drm_fmt = DRM_FORMAT_YVU422, | ||
234 | .de2_fmt = SUN8I_MIXER_FBFMT_YUV422, | ||
235 | .rgb = false, | ||
236 | .csc = SUN8I_CSC_MODE_YVU2RGB, | ||
237 | }, | ||
238 | { | ||
239 | .drm_fmt = DRM_FORMAT_YVU420, | ||
240 | .de2_fmt = SUN8I_MIXER_FBFMT_YUV420, | ||
241 | .rgb = false, | ||
242 | .csc = SUN8I_CSC_MODE_YVU2RGB, | ||
243 | }, | ||
244 | { | ||
245 | .drm_fmt = DRM_FORMAT_YVU411, | ||
246 | .de2_fmt = SUN8I_MIXER_FBFMT_YUV411, | ||
247 | .rgb = false, | ||
248 | .csc = SUN8I_CSC_MODE_YVU2RGB, | ||
249 | }, | ||
250 | }; | ||
91 | 251 | ||
92 | int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, | 252 | const struct de2_fmt_info *sun8i_mixer_format_info(u32 format) |
93 | int layer, struct drm_plane *plane) | ||
94 | { | 253 | { |
95 | struct drm_plane_state *state = plane->state; | 254 | unsigned int i; |
96 | struct drm_framebuffer *fb = state->fb; | ||
97 | /* Currently the first UI channel is used */ | ||
98 | int chan = mixer->cfg->vi_num; | ||
99 | |||
100 | DRM_DEBUG_DRIVER("Updating layer %d\n", layer); | ||
101 | |||
102 | if (plane->type == DRM_PLANE_TYPE_PRIMARY) { | ||
103 | DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n", | ||
104 | state->crtc_w, state->crtc_h); | ||
105 | regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_SIZE, | ||
106 | SUN8I_MIXER_SIZE(state->crtc_w, | ||
107 | state->crtc_h)); | ||
108 | DRM_DEBUG_DRIVER("Updating blender size\n"); | ||
109 | regmap_write(mixer->engine.regs, | ||
110 | SUN8I_MIXER_BLEND_ATTR_INSIZE(0), | ||
111 | SUN8I_MIXER_SIZE(state->crtc_w, | ||
112 | state->crtc_h)); | ||
113 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTSIZE, | ||
114 | SUN8I_MIXER_SIZE(state->crtc_w, | ||
115 | state->crtc_h)); | ||
116 | DRM_DEBUG_DRIVER("Updating channel size\n"); | ||
117 | regmap_write(mixer->engine.regs, | ||
118 | SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan), | ||
119 | SUN8I_MIXER_SIZE(state->crtc_w, | ||
120 | state->crtc_h)); | ||
121 | } | ||
122 | 255 | ||
123 | /* Set the line width */ | 256 | for (i = 0; i < ARRAY_SIZE(de2_formats); ++i) |
124 | DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]); | 257 | if (de2_formats[i].drm_fmt == format) |
125 | regmap_write(mixer->engine.regs, | 258 | return &de2_formats[i]; |
126 | SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer), | ||
127 | fb->pitches[0]); | ||
128 | |||
129 | /* Set height and width */ | ||
130 | DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", | ||
131 | state->crtc_w, state->crtc_h); | ||
132 | regmap_write(mixer->engine.regs, | ||
133 | SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer), | ||
134 | SUN8I_MIXER_SIZE(state->crtc_w, state->crtc_h)); | ||
135 | |||
136 | /* Set base coordinates */ | ||
137 | DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n", | ||
138 | state->crtc_x, state->crtc_y); | ||
139 | regmap_write(mixer->engine.regs, | ||
140 | SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer), | ||
141 | SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y)); | ||
142 | 259 | ||
143 | return 0; | 260 | return NULL; |
144 | } | 261 | } |
145 | 262 | ||
146 | int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer, | 263 | static void sun8i_mixer_commit(struct sunxi_engine *engine) |
147 | int layer, struct drm_plane *plane) | ||
148 | { | 264 | { |
149 | struct drm_plane_state *state = plane->state; | 265 | DRM_DEBUG_DRIVER("Committing changes\n"); |
150 | struct drm_framebuffer *fb = state->fb; | ||
151 | bool interlaced = false; | ||
152 | u32 val; | ||
153 | /* Currently the first UI channel is used */ | ||
154 | int chan = mixer->cfg->vi_num; | ||
155 | int ret; | ||
156 | |||
157 | if (plane->state->crtc) | ||
158 | interlaced = plane->state->crtc->state->adjusted_mode.flags | ||
159 | & DRM_MODE_FLAG_INTERLACE; | ||
160 | |||
161 | regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTCTL, | ||
162 | SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, | ||
163 | interlaced ? | ||
164 | SUN8I_MIXER_BLEND_OUTCTL_INTERLACED : 0); | ||
165 | |||
166 | DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n", | ||
167 | interlaced ? "on" : "off"); | ||
168 | |||
169 | ret = sun8i_mixer_drm_format_to_layer(plane, fb->format->format, | ||
170 | &val); | ||
171 | if (ret) { | ||
172 | DRM_DEBUG_DRIVER("Invalid format\n"); | ||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | regmap_update_bits(mixer->engine.regs, | ||
177 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer), | ||
178 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val); | ||
179 | 266 | ||
180 | return 0; | 267 | regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF, |
268 | SUN8I_MIXER_GLOBAL_DBUFF_ENABLE); | ||
181 | } | 269 | } |
182 | 270 | ||
183 | int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer, | 271 | static struct drm_plane **sun8i_layers_init(struct drm_device *drm, |
184 | int layer, struct drm_plane *plane) | 272 | struct sunxi_engine *engine) |
185 | { | 273 | { |
186 | struct drm_plane_state *state = plane->state; | 274 | struct drm_plane **planes; |
187 | struct drm_framebuffer *fb = state->fb; | 275 | struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); |
188 | struct drm_gem_cma_object *gem; | 276 | int i; |
189 | dma_addr_t paddr; | 277 | |
190 | /* Currently the first UI channel is used */ | 278 | planes = devm_kcalloc(drm->dev, |
191 | int chan = mixer->cfg->vi_num; | 279 | mixer->cfg->vi_num + mixer->cfg->ui_num + 1, |
192 | int bpp; | 280 | sizeof(*planes), GFP_KERNEL); |
193 | 281 | if (!planes) | |
194 | /* Get the physical address of the buffer in memory */ | 282 | return ERR_PTR(-ENOMEM); |
195 | gem = drm_fb_cma_get_gem_obj(fb, 0); | 283 | |
196 | 284 | for (i = 0; i < mixer->cfg->vi_num; i++) { | |
197 | DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr); | 285 | struct sun8i_vi_layer *layer; |
198 | 286 | ||
199 | /* Compute the start of the displayed memory */ | 287 | layer = sun8i_vi_layer_init_one(drm, mixer, i); |
200 | bpp = fb->format->cpp[0]; | 288 | if (IS_ERR(layer)) { |
201 | paddr = gem->paddr + fb->offsets[0]; | 289 | dev_err(drm->dev, |
202 | 290 | "Couldn't initialize overlay plane\n"); | |
203 | /* Fixup framebuffer address for src coordinates */ | 291 | return ERR_CAST(layer); |
204 | paddr += (state->src_x >> 16) * bpp; | 292 | }; |
205 | paddr += (state->src_y >> 16) * fb->pitches[0]; | 293 | |
206 | 294 | planes[i] = &layer->plane; | |
207 | /* | 295 | }; |
208 | * The hardware cannot correctly deal with negative crtc | 296 | |
209 | * coordinates, the display is cropped to the requested size, | 297 | for (i = 0; i < mixer->cfg->ui_num; i++) { |
210 | * but the display content is not moved. | 298 | struct sun8i_ui_layer *layer; |
211 | * Manually move the display content by fixup the framebuffer | 299 | |
212 | * address when crtc_x or crtc_y is negative, like what we | 300 | layer = sun8i_ui_layer_init_one(drm, mixer, i); |
213 | * have did for src_x and src_y. | 301 | if (IS_ERR(layer)) { |
214 | */ | 302 | dev_err(drm->dev, "Couldn't initialize %s plane\n", |
215 | if (state->crtc_x < 0) | 303 | i ? "overlay" : "primary"); |
216 | paddr += -state->crtc_x * bpp; | 304 | return ERR_CAST(layer); |
217 | if (state->crtc_y < 0) | 305 | }; |
218 | paddr += -state->crtc_y * fb->pitches[0]; | 306 | |
219 | 307 | planes[mixer->cfg->vi_num + i] = &layer->plane; | |
220 | DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr); | 308 | }; |
221 | 309 | ||
222 | regmap_write(mixer->engine.regs, | 310 | return planes; |
223 | SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer), | ||
224 | lower_32_bits(paddr)); | ||
225 | |||
226 | return 0; | ||
227 | } | 311 | } |
228 | 312 | ||
229 | static const struct sunxi_engine_ops sun8i_engine_ops = { | 313 | static const struct sunxi_engine_ops sun8i_engine_ops = { |
@@ -247,6 +331,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, | |||
247 | struct sun8i_mixer *mixer; | 331 | struct sun8i_mixer *mixer; |
248 | struct resource *res; | 332 | struct resource *res; |
249 | void __iomem *regs; | 333 | void __iomem *regs; |
334 | int plane_cnt; | ||
250 | int i, ret; | 335 | int i, ret; |
251 | 336 | ||
252 | /* | 337 | /* |
@@ -325,27 +410,26 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, | |||
325 | regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL, | 410 | regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL, |
326 | SUN8I_MIXER_GLOBAL_CTL_RT_EN); | 411 | SUN8I_MIXER_GLOBAL_CTL_RT_EN); |
327 | 412 | ||
328 | /* Initialize blender */ | 413 | /* Set background color to black */ |
329 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_FCOLOR_CTL, | ||
330 | SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF); | ||
331 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PREMULTIPLY, | ||
332 | SUN8I_MIXER_BLEND_PREMULTIPLY_DEF); | ||
333 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR, | 414 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR, |
334 | SUN8I_MIXER_BLEND_BKCOLOR_DEF); | 415 | SUN8I_MIXER_BLEND_COLOR_BLACK); |
335 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(0), | 416 | |
336 | SUN8I_MIXER_BLEND_MODE_DEF); | 417 | /* |
337 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_CK_CTL, | 418 | * Set fill color of bottom plane to black. Generally not needed |
338 | SUN8I_MIXER_BLEND_CK_CTL_DEF); | 419 | * except when VI plane is at bottom (zpos = 0) and enabled. |
339 | 420 | */ | |
340 | regmap_write(mixer->engine.regs, | 421 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL, |
341 | SUN8I_MIXER_BLEND_ATTR_FCOLOR(0), | 422 | SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0)); |
342 | SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF); | 423 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(0), |
343 | 424 | SUN8I_MIXER_BLEND_COLOR_BLACK); | |
344 | /* Select the first UI channel */ | 425 | |
345 | DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n", | 426 | /* Fixed zpos for now */ |
346 | mixer->cfg->vi_num); | 427 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 0x43210); |
347 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, | 428 | |
348 | mixer->cfg->vi_num); | 429 | plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num; |
430 | for (i = 0; i < plane_cnt; i++) | ||
431 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(i), | ||
432 | SUN8I_MIXER_BLEND_MODE_DEF); | ||
349 | 433 | ||
350 | return 0; | 434 | return 0; |
351 | 435 | ||
@@ -388,6 +472,8 @@ static int sun8i_mixer_remove(struct platform_device *pdev) | |||
388 | static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { | 472 | static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { |
389 | .vi_num = 2, | 473 | .vi_num = 2, |
390 | .ui_num = 1, | 474 | .ui_num = 1, |
475 | .scaler_mask = 0x3, | ||
476 | .ccsc = 0, | ||
391 | }; | 477 | }; |
392 | 478 | ||
393 | static const struct of_device_id sun8i_mixer_of_table[] = { | 479 | static const struct of_device_id sun8i_mixer_of_table[] = { |
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h index 4785ac090b8c..bc58040a88f9 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h | |||
@@ -14,10 +14,9 @@ | |||
14 | #include <linux/regmap.h> | 14 | #include <linux/regmap.h> |
15 | #include <linux/reset.h> | 15 | #include <linux/reset.h> |
16 | 16 | ||
17 | #include "sun8i_csc.h" | ||
17 | #include "sunxi_engine.h" | 18 | #include "sunxi_engine.h" |
18 | 19 | ||
19 | #define SUN8I_MIXER_MAX_CHAN_COUNT 4 | ||
20 | |||
21 | #define SUN8I_MIXER_SIZE(w, h) (((h) - 1) << 16 | ((w) - 1)) | 20 | #define SUN8I_MIXER_SIZE(w, h) (((h) - 1) << 16 | ((w) - 1)) |
22 | #define SUN8I_MIXER_COORD(x, y) ((y) << 16 | (x)) | 21 | #define SUN8I_MIXER_COORD(x, y) ((y) << 16 | (x)) |
23 | 22 | ||
@@ -26,14 +25,14 @@ | |||
26 | #define SUN8I_MIXER_GLOBAL_DBUFF 0x8 | 25 | #define SUN8I_MIXER_GLOBAL_DBUFF 0x8 |
27 | #define SUN8I_MIXER_GLOBAL_SIZE 0xc | 26 | #define SUN8I_MIXER_GLOBAL_SIZE 0xc |
28 | 27 | ||
29 | #define SUN8I_MIXER_GLOBAL_CTL_RT_EN 0x1 | 28 | #define SUN8I_MIXER_GLOBAL_CTL_RT_EN BIT(0) |
30 | 29 | ||
31 | #define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE 0x1 | 30 | #define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE BIT(0) |
32 | 31 | ||
33 | #define SUN8I_MIXER_BLEND_FCOLOR_CTL 0x1000 | 32 | #define SUN8I_MIXER_BLEND_PIPE_CTL 0x1000 |
34 | #define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x) (0x1004 + 0x10 * (x) + 0x0) | 33 | #define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x) (0x1004 + 0x10 * (x) + 0x0) |
35 | #define SUN8I_MIXER_BLEND_ATTR_INSIZE(x) (0x1004 + 0x10 * (x) + 0x4) | 34 | #define SUN8I_MIXER_BLEND_ATTR_INSIZE(x) (0x1004 + 0x10 * (x) + 0x4) |
36 | #define SUN8I_MIXER_BLEND_ATTR_OFFSET(x) (0x1004 + 0x10 * (x) + 0x8) | 35 | #define SUN8I_MIXER_BLEND_ATTR_COORD(x) (0x1004 + 0x10 * (x) + 0x8) |
37 | #define SUN8I_MIXER_BLEND_ROUTE 0x1080 | 36 | #define SUN8I_MIXER_BLEND_ROUTE 0x1080 |
38 | #define SUN8I_MIXER_BLEND_PREMULTIPLY 0x1084 | 37 | #define SUN8I_MIXER_BLEND_PREMULTIPLY 0x1084 |
39 | #define SUN8I_MIXER_BLEND_BKCOLOR 0x1088 | 38 | #define SUN8I_MIXER_BLEND_BKCOLOR 0x1088 |
@@ -45,57 +44,56 @@ | |||
45 | #define SUN8I_MIXER_BLEND_CK_MIN(x) (0x10e0 + 0x04 * (x)) | 44 | #define SUN8I_MIXER_BLEND_CK_MIN(x) (0x10e0 + 0x04 * (x)) |
46 | #define SUN8I_MIXER_BLEND_OUTCTL 0x10fc | 45 | #define SUN8I_MIXER_BLEND_OUTCTL 0x10fc |
47 | 46 | ||
47 | #define SUN8I_MIXER_BLEND_PIPE_CTL_EN(pipe) BIT(8 + pipe) | ||
48 | #define SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(pipe) BIT(pipe) | ||
49 | /* colors are always in AARRGGBB format */ | ||
50 | #define SUN8I_MIXER_BLEND_COLOR_BLACK 0xff000000 | ||
48 | /* The following numbers are some still unknown magic numbers */ | 51 | /* The following numbers are some still unknown magic numbers */ |
49 | #define SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF 0xff000000 | ||
50 | #define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF 0x00000101 | ||
51 | #define SUN8I_MIXER_BLEND_PREMULTIPLY_DEF 0x0 | ||
52 | #define SUN8I_MIXER_BLEND_BKCOLOR_DEF 0xff000000 | ||
53 | #define SUN8I_MIXER_BLEND_MODE_DEF 0x03010301 | 52 | #define SUN8I_MIXER_BLEND_MODE_DEF 0x03010301 |
54 | #define SUN8I_MIXER_BLEND_CK_CTL_DEF 0x0 | ||
55 | 53 | ||
56 | #define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED BIT(1) | 54 | #define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED BIT(1) |
57 | 55 | ||
58 | /* | 56 | #define SUN8I_MIXER_FBFMT_ARGB8888 0 |
59 | * VI channels are not used now, but the support of them may be introduced in | 57 | #define SUN8I_MIXER_FBFMT_ABGR8888 1 |
60 | * the future. | 58 | #define SUN8I_MIXER_FBFMT_RGBA8888 2 |
61 | */ | 59 | #define SUN8I_MIXER_FBFMT_BGRA8888 3 |
62 | 60 | #define SUN8I_MIXER_FBFMT_XRGB8888 4 | |
63 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \ | 61 | #define SUN8I_MIXER_FBFMT_XBGR8888 5 |
64 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0) | 62 | #define SUN8I_MIXER_FBFMT_RGBX8888 6 |
65 | #define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \ | 63 | #define SUN8I_MIXER_FBFMT_BGRX8888 7 |
66 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4) | 64 | #define SUN8I_MIXER_FBFMT_RGB888 8 |
67 | #define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \ | 65 | #define SUN8I_MIXER_FBFMT_BGR888 9 |
68 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8) | 66 | #define SUN8I_MIXER_FBFMT_RGB565 10 |
69 | #define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \ | 67 | #define SUN8I_MIXER_FBFMT_BGR565 11 |
70 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc) | 68 | #define SUN8I_MIXER_FBFMT_ARGB4444 12 |
71 | #define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \ | 69 | #define SUN8I_MIXER_FBFMT_ABGR4444 13 |
72 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10) | 70 | #define SUN8I_MIXER_FBFMT_RGBA4444 14 |
73 | #define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \ | 71 | #define SUN8I_MIXER_FBFMT_BGRA4444 15 |
74 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14) | 72 | #define SUN8I_MIXER_FBFMT_ARGB1555 16 |
75 | #define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \ | 73 | #define SUN8I_MIXER_FBFMT_ABGR1555 17 |
76 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18) | 74 | #define SUN8I_MIXER_FBFMT_RGBA5551 18 |
77 | #define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch) (0x2000 + 0x1000 * (ch) + 0x80) | 75 | #define SUN8I_MIXER_FBFMT_BGRA5551 19 |
78 | #define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch) (0x2000 + 0x1000 * (ch) + 0x84) | 76 | |
79 | #define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch) (0x2000 + 0x1000 * (ch) + 0x88) | 77 | #define SUN8I_MIXER_FBFMT_YUYV 0 |
80 | 78 | #define SUN8I_MIXER_FBFMT_UYVY 1 | |
81 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN BIT(0) | 79 | #define SUN8I_MIXER_FBFMT_YVYU 2 |
82 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK GENMASK(2, 1) | 80 | #define SUN8I_MIXER_FBFMT_VYUY 3 |
83 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK GENMASK(11, 8) | 81 | #define SUN8I_MIXER_FBFMT_NV16 4 |
84 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK GENMASK(31, 24) | 82 | #define SUN8I_MIXER_FBFMT_NV61 5 |
85 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF (1 << 1) | 83 | #define SUN8I_MIXER_FBFMT_YUV422 6 |
86 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888 (0 << 8) | 84 | /* format 7 doesn't exist */ |
87 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888 (4 << 8) | 85 | #define SUN8I_MIXER_FBFMT_NV12 8 |
88 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888 (8 << 8) | 86 | #define SUN8I_MIXER_FBFMT_NV21 9 |
89 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF (0xff << 24) | 87 | #define SUN8I_MIXER_FBFMT_YUV420 10 |
88 | /* format 11 doesn't exist */ | ||
89 | /* format 12 is semi-planar YUV411 UVUV */ | ||
90 | /* format 13 is semi-planar YUV411 VUVU */ | ||
91 | #define SUN8I_MIXER_FBFMT_YUV411 14 | ||
90 | 92 | ||
91 | /* | 93 | /* |
92 | * These sub-engines are still unknown now, the EN registers are here only to | 94 | * These sub-engines are still unknown now, the EN registers are here only to |
93 | * be used to disable these sub-engines. | 95 | * be used to disable these sub-engines. |
94 | */ | 96 | */ |
95 | #define SUN8I_MIXER_VSU_EN 0x20000 | ||
96 | #define SUN8I_MIXER_GSU1_EN 0x30000 | ||
97 | #define SUN8I_MIXER_GSU2_EN 0x40000 | ||
98 | #define SUN8I_MIXER_GSU3_EN 0x50000 | ||
99 | #define SUN8I_MIXER_FCE_EN 0xa0000 | 97 | #define SUN8I_MIXER_FCE_EN 0xa0000 |
100 | #define SUN8I_MIXER_BWS_EN 0xa2000 | 98 | #define SUN8I_MIXER_BWS_EN 0xa2000 |
101 | #define SUN8I_MIXER_LTI_EN 0xa4000 | 99 | #define SUN8I_MIXER_LTI_EN 0xa4000 |
@@ -104,9 +102,31 @@ | |||
104 | #define SUN8I_MIXER_FCC_EN 0xaa000 | 102 | #define SUN8I_MIXER_FCC_EN 0xaa000 |
105 | #define SUN8I_MIXER_DCSC_EN 0xb0000 | 103 | #define SUN8I_MIXER_DCSC_EN 0xb0000 |
106 | 104 | ||
105 | struct de2_fmt_info { | ||
106 | u32 drm_fmt; | ||
107 | u32 de2_fmt; | ||
108 | bool rgb; | ||
109 | enum sun8i_csc_mode csc; | ||
110 | }; | ||
111 | |||
112 | /** | ||
113 | * struct sun8i_mixer_cfg - mixer HW configuration | ||
114 | * @vi_num: number of VI channels | ||
115 | * @ui_num: number of UI channels | ||
116 | * @scaler_mask: bitmask which tells which channel supports scaling | ||
117 | * First, scaler supports for VI channels is defined and after that, scaler | ||
118 | * support for UI channels. For example, if mixer has 2 VI channels without | ||
119 | * scaler and 2 UI channels with scaler, bitmask would be 0xC. | ||
120 | * @ccsc: select set of CCSC base addresses | ||
121 | * Set value to 0 if this is first mixer or second mixer with VEP support. | ||
122 | * Set value to 1 if this is second mixer without VEP support. Other values | ||
123 | * are invalid. | ||
124 | */ | ||
107 | struct sun8i_mixer_cfg { | 125 | struct sun8i_mixer_cfg { |
108 | int vi_num; | 126 | int vi_num; |
109 | int ui_num; | 127 | int ui_num; |
128 | int scaler_mask; | ||
129 | int ccsc; | ||
110 | }; | 130 | }; |
111 | 131 | ||
112 | struct sun8i_mixer { | 132 | struct sun8i_mixer { |
@@ -126,12 +146,5 @@ engine_to_sun8i_mixer(struct sunxi_engine *engine) | |||
126 | return container_of(engine, struct sun8i_mixer, engine); | 146 | return container_of(engine, struct sun8i_mixer, engine); |
127 | } | 147 | } |
128 | 148 | ||
129 | void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, | 149 | const struct de2_fmt_info *sun8i_mixer_format_info(u32 format); |
130 | int layer, bool enable); | ||
131 | int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, | ||
132 | int layer, struct drm_plane *plane); | ||
133 | int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer, | ||
134 | int layer, struct drm_plane *plane); | ||
135 | int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer, | ||
136 | int layer, struct drm_plane *plane); | ||
137 | #endif /* _SUN8I_MIXER_H_ */ | 150 | #endif /* _SUN8I_MIXER_H_ */ |
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c new file mode 100644 index 000000000000..28d7c48d50fe --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /* | ||
2 | * Copyright (C) Icenowy Zheng <icenowy@aosc.io> | ||
3 | * | ||
4 | * Based on sun4i_layer.h, which is: | ||
5 | * Copyright (C) 2015 Free Electrons | ||
6 | * Copyright (C) 2015 NextThing Co | ||
7 | * | ||
8 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation; either version 2 of | ||
13 | * the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <drm/drm_atomic.h> | ||
17 | #include <drm/drm_atomic_helper.h> | ||
18 | #include <drm/drm_crtc.h> | ||
19 | #include <drm/drm_crtc_helper.h> | ||
20 | #include <drm/drm_fb_cma_helper.h> | ||
21 | #include <drm/drm_gem_cma_helper.h> | ||
22 | #include <drm/drm_plane_helper.h> | ||
23 | #include <drm/drmP.h> | ||
24 | |||
25 | #include "sun8i_ui_layer.h" | ||
26 | #include "sun8i_mixer.h" | ||
27 | #include "sun8i_ui_scaler.h" | ||
28 | |||
29 | static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel, | ||
30 | int overlay, bool enable) | ||
31 | { | ||
32 | u32 val; | ||
33 | |||
34 | DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n", | ||
35 | enable ? "En" : "Dis", channel, overlay); | ||
36 | |||
37 | if (enable) | ||
38 | val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN; | ||
39 | else | ||
40 | val = 0; | ||
41 | |||
42 | regmap_update_bits(mixer->engine.regs, | ||
43 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay), | ||
44 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val); | ||
45 | |||
46 | if (enable) | ||
47 | val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel); | ||
48 | else | ||
49 | val = 0; | ||
50 | |||
51 | regmap_update_bits(mixer->engine.regs, | ||
52 | SUN8I_MIXER_BLEND_PIPE_CTL, | ||
53 | SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val); | ||
54 | } | ||
55 | |||
56 | static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel, | ||
57 | int overlay, struct drm_plane *plane) | ||
58 | { | ||
59 | struct drm_plane_state *state = plane->state; | ||
60 | u32 src_w, src_h, dst_w, dst_h; | ||
61 | u32 outsize, insize; | ||
62 | u32 hphase, vphase; | ||
63 | |||
64 | DRM_DEBUG_DRIVER("Updating UI channel %d overlay %d\n", | ||
65 | channel, overlay); | ||
66 | |||
67 | src_w = drm_rect_width(&state->src) >> 16; | ||
68 | src_h = drm_rect_height(&state->src) >> 16; | ||
69 | dst_w = drm_rect_width(&state->dst); | ||
70 | dst_h = drm_rect_height(&state->dst); | ||
71 | |||
72 | hphase = state->src.x1 & 0xffff; | ||
73 | vphase = state->src.y1 & 0xffff; | ||
74 | |||
75 | insize = SUN8I_MIXER_SIZE(src_w, src_h); | ||
76 | outsize = SUN8I_MIXER_SIZE(dst_w, dst_h); | ||
77 | |||
78 | if (plane->type == DRM_PLANE_TYPE_PRIMARY) { | ||
79 | bool interlaced = false; | ||
80 | u32 val; | ||
81 | |||
82 | DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n", | ||
83 | dst_w, dst_h); | ||
84 | regmap_write(mixer->engine.regs, | ||
85 | SUN8I_MIXER_GLOBAL_SIZE, | ||
86 | outsize); | ||
87 | regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTSIZE, | ||
88 | outsize); | ||
89 | |||
90 | if (state->crtc) | ||
91 | interlaced = state->crtc->state->adjusted_mode.flags | ||
92 | & DRM_MODE_FLAG_INTERLACE; | ||
93 | |||
94 | if (interlaced) | ||
95 | val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED; | ||
96 | else | ||
97 | val = 0; | ||
98 | |||
99 | regmap_update_bits(mixer->engine.regs, | ||
100 | SUN8I_MIXER_BLEND_OUTCTL, | ||
101 | SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, | ||
102 | val); | ||
103 | |||
104 | DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n", | ||
105 | interlaced ? "on" : "off"); | ||
106 | } | ||
107 | |||
108 | /* Set height and width */ | ||
109 | DRM_DEBUG_DRIVER("Layer source offset X: %d Y: %d\n", | ||
110 | state->src.x1 >> 16, state->src.y1 >> 16); | ||
111 | DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h); | ||
112 | regmap_write(mixer->engine.regs, | ||
113 | SUN8I_MIXER_CHAN_UI_LAYER_SIZE(channel, overlay), | ||
114 | insize); | ||
115 | regmap_write(mixer->engine.regs, | ||
116 | SUN8I_MIXER_CHAN_UI_OVL_SIZE(channel), | ||
117 | insize); | ||
118 | |||
119 | if (insize != outsize || hphase || vphase) { | ||
120 | u32 hscale, vscale; | ||
121 | |||
122 | DRM_DEBUG_DRIVER("HW scaling is enabled\n"); | ||
123 | |||
124 | hscale = state->src_w / state->crtc_w; | ||
125 | vscale = state->src_h / state->crtc_h; | ||
126 | |||
127 | sun8i_ui_scaler_setup(mixer, channel, src_w, src_h, dst_w, | ||
128 | dst_h, hscale, vscale, hphase, vphase); | ||
129 | sun8i_ui_scaler_enable(mixer, channel, true); | ||
130 | } else { | ||
131 | DRM_DEBUG_DRIVER("HW scaling is not needed\n"); | ||
132 | sun8i_ui_scaler_enable(mixer, channel, false); | ||
133 | } | ||
134 | |||
135 | /* Set base coordinates */ | ||
136 | DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n", | ||
137 | state->dst.x1, state->dst.y1); | ||
138 | DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h); | ||
139 | regmap_write(mixer->engine.regs, | ||
140 | SUN8I_MIXER_BLEND_ATTR_COORD(channel), | ||
141 | SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1)); | ||
142 | regmap_write(mixer->engine.regs, | ||
143 | SUN8I_MIXER_BLEND_ATTR_INSIZE(channel), | ||
144 | outsize); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int sun8i_ui_layer_update_formats(struct sun8i_mixer *mixer, int channel, | ||
150 | int overlay, struct drm_plane *plane) | ||
151 | { | ||
152 | struct drm_plane_state *state = plane->state; | ||
153 | const struct de2_fmt_info *fmt_info; | ||
154 | u32 val; | ||
155 | |||
156 | fmt_info = sun8i_mixer_format_info(state->fb->format->format); | ||
157 | if (!fmt_info || !fmt_info->rgb) { | ||
158 | DRM_DEBUG_DRIVER("Invalid format\n"); | ||
159 | return -EINVAL; | ||
160 | } | ||
161 | |||
162 | val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET; | ||
163 | regmap_update_bits(mixer->engine.regs, | ||
164 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay), | ||
165 | SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val); | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static int sun8i_ui_layer_update_buffer(struct sun8i_mixer *mixer, int channel, | ||
171 | int overlay, struct drm_plane *plane) | ||
172 | { | ||
173 | struct drm_plane_state *state = plane->state; | ||
174 | struct drm_framebuffer *fb = state->fb; | ||
175 | struct drm_gem_cma_object *gem; | ||
176 | dma_addr_t paddr; | ||
177 | int bpp; | ||
178 | |||
179 | /* Get the physical address of the buffer in memory */ | ||
180 | gem = drm_fb_cma_get_gem_obj(fb, 0); | ||
181 | |||
182 | DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr); | ||
183 | |||
184 | /* Compute the start of the displayed memory */ | ||
185 | bpp = fb->format->cpp[0]; | ||
186 | paddr = gem->paddr + fb->offsets[0]; | ||
187 | |||
188 | /* Fixup framebuffer address for src coordinates */ | ||
189 | paddr += (state->src.x1 >> 16) * bpp; | ||
190 | paddr += (state->src.y1 >> 16) * fb->pitches[0]; | ||
191 | |||
192 | /* Set the line width */ | ||
193 | DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]); | ||
194 | regmap_write(mixer->engine.regs, | ||
195 | SUN8I_MIXER_CHAN_UI_LAYER_PITCH(channel, overlay), | ||
196 | fb->pitches[0]); | ||
197 | |||
198 | DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr); | ||
199 | |||
200 | regmap_write(mixer->engine.regs, | ||
201 | SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(channel, overlay), | ||
202 | lower_32_bits(paddr)); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static int sun8i_ui_layer_atomic_check(struct drm_plane *plane, | ||
208 | struct drm_plane_state *state) | ||
209 | { | ||
210 | struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane); | ||
211 | struct drm_crtc *crtc = state->crtc; | ||
212 | struct drm_crtc_state *crtc_state; | ||
213 | int min_scale, max_scale; | ||
214 | struct drm_rect clip; | ||
215 | |||
216 | if (!crtc) | ||
217 | return 0; | ||
218 | |||
219 | crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); | ||
220 | if (WARN_ON(!crtc_state)) | ||
221 | return -EINVAL; | ||
222 | |||
223 | clip.x1 = 0; | ||
224 | clip.y1 = 0; | ||
225 | clip.x2 = crtc_state->adjusted_mode.hdisplay; | ||
226 | clip.y2 = crtc_state->adjusted_mode.vdisplay; | ||
227 | |||
228 | min_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
229 | max_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
230 | |||
231 | if (layer->mixer->cfg->scaler_mask & BIT(layer->channel)) { | ||
232 | min_scale = SUN8I_UI_SCALER_SCALE_MIN; | ||
233 | max_scale = SUN8I_UI_SCALER_SCALE_MAX; | ||
234 | } | ||
235 | |||
236 | return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
237 | min_scale, max_scale, | ||
238 | true, true); | ||
239 | } | ||
240 | |||
241 | static void sun8i_ui_layer_atomic_disable(struct drm_plane *plane, | ||
242 | struct drm_plane_state *old_state) | ||
243 | { | ||
244 | struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane); | ||
245 | struct sun8i_mixer *mixer = layer->mixer; | ||
246 | |||
247 | sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false); | ||
248 | } | ||
249 | |||
250 | static void sun8i_ui_layer_atomic_update(struct drm_plane *plane, | ||
251 | struct drm_plane_state *old_state) | ||
252 | { | ||
253 | struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane); | ||
254 | struct sun8i_mixer *mixer = layer->mixer; | ||
255 | |||
256 | if (!plane->state->visible) { | ||
257 | sun8i_ui_layer_enable(mixer, layer->channel, | ||
258 | layer->overlay, false); | ||
259 | return; | ||
260 | } | ||
261 | |||
262 | sun8i_ui_layer_update_coord(mixer, layer->channel, | ||
263 | layer->overlay, plane); | ||
264 | sun8i_ui_layer_update_formats(mixer, layer->channel, | ||
265 | layer->overlay, plane); | ||
266 | sun8i_ui_layer_update_buffer(mixer, layer->channel, | ||
267 | layer->overlay, plane); | ||
268 | sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, true); | ||
269 | } | ||
270 | |||
271 | static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = { | ||
272 | .atomic_check = sun8i_ui_layer_atomic_check, | ||
273 | .atomic_disable = sun8i_ui_layer_atomic_disable, | ||
274 | .atomic_update = sun8i_ui_layer_atomic_update, | ||
275 | }; | ||
276 | |||
277 | static const struct drm_plane_funcs sun8i_ui_layer_funcs = { | ||
278 | .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, | ||
279 | .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, | ||
280 | .destroy = drm_plane_cleanup, | ||
281 | .disable_plane = drm_atomic_helper_disable_plane, | ||
282 | .reset = drm_atomic_helper_plane_reset, | ||
283 | .update_plane = drm_atomic_helper_update_plane, | ||
284 | }; | ||
285 | |||
286 | static const u32 sun8i_ui_layer_formats[] = { | ||
287 | DRM_FORMAT_ABGR1555, | ||
288 | DRM_FORMAT_ABGR4444, | ||
289 | DRM_FORMAT_ABGR8888, | ||
290 | DRM_FORMAT_ARGB1555, | ||
291 | DRM_FORMAT_ARGB4444, | ||
292 | DRM_FORMAT_ARGB8888, | ||
293 | DRM_FORMAT_BGR565, | ||
294 | DRM_FORMAT_BGR888, | ||
295 | DRM_FORMAT_BGRA5551, | ||
296 | DRM_FORMAT_BGRA4444, | ||
297 | DRM_FORMAT_BGRA8888, | ||
298 | DRM_FORMAT_BGRX8888, | ||
299 | DRM_FORMAT_RGB565, | ||
300 | DRM_FORMAT_RGB888, | ||
301 | DRM_FORMAT_RGBA4444, | ||
302 | DRM_FORMAT_RGBA5551, | ||
303 | DRM_FORMAT_RGBA8888, | ||
304 | DRM_FORMAT_RGBX8888, | ||
305 | DRM_FORMAT_XBGR8888, | ||
306 | DRM_FORMAT_XRGB8888, | ||
307 | }; | ||
308 | |||
309 | struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm, | ||
310 | struct sun8i_mixer *mixer, | ||
311 | int index) | ||
312 | { | ||
313 | enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY; | ||
314 | int channel = mixer->cfg->vi_num + index; | ||
315 | struct sun8i_ui_layer *layer; | ||
316 | int ret; | ||
317 | |||
318 | layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL); | ||
319 | if (!layer) | ||
320 | return ERR_PTR(-ENOMEM); | ||
321 | |||
322 | if (index == 0) | ||
323 | type = DRM_PLANE_TYPE_PRIMARY; | ||
324 | |||
325 | /* possible crtcs are set later */ | ||
326 | ret = drm_universal_plane_init(drm, &layer->plane, 0, | ||
327 | &sun8i_ui_layer_funcs, | ||
328 | sun8i_ui_layer_formats, | ||
329 | ARRAY_SIZE(sun8i_ui_layer_formats), | ||
330 | NULL, type, NULL); | ||
331 | if (ret) { | ||
332 | dev_err(drm->dev, "Couldn't initialize layer\n"); | ||
333 | return ERR_PTR(ret); | ||
334 | } | ||
335 | |||
336 | /* fixed zpos for now */ | ||
337 | ret = drm_plane_create_zpos_immutable_property(&layer->plane, channel); | ||
338 | if (ret) { | ||
339 | dev_err(drm->dev, "Couldn't add zpos property\n"); | ||
340 | return ERR_PTR(ret); | ||
341 | } | ||
342 | |||
343 | drm_plane_helper_add(&layer->plane, &sun8i_ui_layer_helper_funcs); | ||
344 | layer->mixer = mixer; | ||
345 | layer->channel = channel; | ||
346 | layer->overlay = 0; | ||
347 | |||
348 | return layer; | ||
349 | } | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.h b/drivers/gpu/drm/sun4i/sun8i_ui_layer.h new file mode 100644 index 000000000000..123b15ea9918 --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Copyright (C) Icenowy Zheng <icenowy@aosc.io> | ||
3 | * | ||
4 | * Based on sun4i_layer.h, which is: | ||
5 | * Copyright (C) 2015 Free Electrons | ||
6 | * Copyright (C) 2015 NextThing Co | ||
7 | * | ||
8 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation; either version 2 of | ||
13 | * the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifndef _SUN8I_UI_LAYER_H_ | ||
17 | #define _SUN8I_UI_LAYER_H_ | ||
18 | |||
19 | #include <drm/drm_plane.h> | ||
20 | |||
21 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \ | ||
22 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0) | ||
23 | #define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \ | ||
24 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4) | ||
25 | #define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \ | ||
26 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8) | ||
27 | #define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \ | ||
28 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc) | ||
29 | #define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \ | ||
30 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10) | ||
31 | #define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \ | ||
32 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14) | ||
33 | #define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \ | ||
34 | (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18) | ||
35 | #define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch) (0x2000 + 0x1000 * (ch) + 0x80) | ||
36 | #define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch) (0x2000 + 0x1000 * (ch) + 0x84) | ||
37 | #define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch) (0x2000 + 0x1000 * (ch) + 0x88) | ||
38 | |||
39 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN BIT(0) | ||
40 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK GENMASK(2, 1) | ||
41 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK GENMASK(12, 8) | ||
42 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET 8 | ||
43 | #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK GENMASK(31, 24) | ||
44 | |||
45 | struct sun8i_mixer; | ||
46 | |||
47 | struct sun8i_ui_layer { | ||
48 | struct drm_plane plane; | ||
49 | struct sun8i_mixer *mixer; | ||
50 | int channel; | ||
51 | int overlay; | ||
52 | }; | ||
53 | |||
54 | static inline struct sun8i_ui_layer * | ||
55 | plane_to_sun8i_ui_layer(struct drm_plane *plane) | ||
56 | { | ||
57 | return container_of(plane, struct sun8i_ui_layer, plane); | ||
58 | } | ||
59 | |||
60 | struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm, | ||
61 | struct sun8i_mixer *mixer, | ||
62 | int index); | ||
63 | #endif /* _SUN8I_UI_LAYER_H_ */ | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c new file mode 100644 index 000000000000..6bb2aa164c8e --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Jernej Skrabec <jernej.skrabec@siol.net> | ||
3 | * | ||
4 | * Coefficients are taken from BSP driver, which is: | ||
5 | * Copyright (C) 2014-2015 Allwinner | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include "sun8i_ui_scaler.h" | ||
13 | |||
14 | static const u32 lan2coefftab16[240] = { | ||
15 | 0x00004000, 0x00033ffe, 0x00063efc, 0x000a3bfb, | ||
16 | 0xff0f37fb, 0xfe1433fb, 0xfd192ffb, 0xfd1f29fb, | ||
17 | 0xfc2424fc, 0xfb291ffd, 0xfb2f19fd, 0xfb3314fe, | ||
18 | 0xfb370fff, 0xfb3b0a00, 0xfc3e0600, 0xfe3f0300, | ||
19 | |||
20 | 0xff053804, 0xff083801, 0xff0a3700, 0xff0e34ff, | ||
21 | 0xff1232fd, 0xfe162ffd, 0xfd1b2cfc, 0xfd1f28fc, | ||
22 | 0xfd2323fd, 0xfc281ffd, 0xfc2c1bfd, 0xfd2f16fe, | ||
23 | 0xfd3212ff, 0xff340eff, 0x00360a00, 0x02370700, | ||
24 | |||
25 | 0xff083207, 0xff0a3205, 0xff0d3103, 0xfe113001, | ||
26 | 0xfe142e00, 0xfe182bff, 0xfe1b29fe, 0xfe1f25fe, | ||
27 | 0xfe2222fe, 0xfe251ffe, 0xfe291bfe, 0xff2b18fe, | ||
28 | 0x002e14fe, 0x013010ff, 0x03310dff, 0x05310a00, | ||
29 | |||
30 | 0xff0a2e09, 0xff0c2e07, 0xff0f2d05, 0xff122c03, | ||
31 | 0xfe152b02, 0xfe182901, 0xfe1b2700, 0xff1e24ff, | ||
32 | 0xff2121ff, 0xff241eff, 0x00261bff, 0x012818ff, | ||
33 | 0x022a15ff, 0x032c12ff, 0x052d0fff, 0x072d0c00, | ||
34 | |||
35 | 0xff0c2a0b, 0xff0e2a09, 0xff102a07, 0xff132905, | ||
36 | 0xff162803, 0xff182702, 0xff1b2501, 0xff1e2300, | ||
37 | 0x00202000, 0x01221d00, 0x01251bff, 0x032618ff, | ||
38 | 0x042815ff, 0x052913ff, 0x072a10ff, 0x092a0d00, | ||
39 | |||
40 | 0xff0d280c, 0xff0f280a, 0xff112808, 0xff142706, | ||
41 | 0xff162605, 0xff192503, 0x001b2302, 0x001d2201, | ||
42 | 0x011f1f01, 0x01221d00, 0x02231b00, 0x04241800, | ||
43 | 0x052616ff, 0x072713ff, 0x08271100, 0x0a280e00, | ||
44 | |||
45 | 0xff0e260d, 0xff10260b, 0xff122609, 0xff142508, | ||
46 | 0x00152506, 0x00182305, 0x001b2203, 0x011d2002, | ||
47 | 0x011f1f01, 0x02201d01, 0x03221b00, 0x04231801, | ||
48 | 0x06241600, 0x08251300, 0x09261100, 0x0b260f00, | ||
49 | |||
50 | 0xff0e250e, 0xff10250c, 0x0011250a, 0x00142408, | ||
51 | 0x00162307, 0x00182206, 0x011a2104, 0x011c2003, | ||
52 | 0x021e1e02, 0x03201c01, 0x04211a01, 0x05221801, | ||
53 | 0x07231600, 0x08241400, 0x0a241200, 0x0c241000, | ||
54 | |||
55 | 0x000e240e, 0x0010240c, 0x0013230a, 0x00142309, | ||
56 | 0x00162208, 0x01182106, 0x011a2005, 0x021b1f04, | ||
57 | 0x031d1d03, 0x041e1c02, 0x05201a01, 0x06211801, | ||
58 | 0x07221601, 0x09231400, 0x0a231300, 0x0c231100, | ||
59 | |||
60 | 0x000f220f, 0x0011220d, 0x0013220b, 0x0015210a, | ||
61 | 0x01162108, 0x01182007, 0x02191f06, 0x031a1e05, | ||
62 | 0x041c1c04, 0x051d1b03, 0x061f1902, 0x07201801, | ||
63 | 0x08211601, 0x0a211500, 0x0b221300, 0x0d221100, | ||
64 | |||
65 | 0x0010210f, 0x0011210e, 0x0013210c, 0x0114200b, | ||
66 | 0x01161f0a, 0x02171f08, 0x03181e07, 0x031a1d06, | ||
67 | 0x041c1c04, 0x051d1a04, 0x071d1903, 0x081e1802, | ||
68 | 0x091f1602, 0x0b1f1501, 0x0c211300, 0x0e201200, | ||
69 | |||
70 | 0x00102010, 0x0012200e, 0x0013200d, 0x01151f0b, | ||
71 | 0x01161f0a, 0x02171e09, 0x03191d07, 0x041a1c06, | ||
72 | 0x051b1b05, 0x061c1a04, 0x071d1903, 0x081e1703, | ||
73 | 0x0a1f1601, 0x0b1f1501, 0x0d201300, 0x0e201200, | ||
74 | |||
75 | 0x00102010, 0x00121f0f, 0x00141f0d, 0x01141f0c, | ||
76 | 0x02161e0a, 0x03171d09, 0x03181d08, 0x041a1c06, | ||
77 | 0x051b1b05, 0x061c1a04, 0x081c1903, 0x091d1703, | ||
78 | 0x0a1e1602, 0x0c1e1501, 0x0d1f1400, 0x0e1f1201, | ||
79 | |||
80 | 0x00111e11, 0x00131e0f, 0x01131e0e, 0x02151d0c, | ||
81 | 0x02161d0b, 0x03171c0a, 0x04181b09, 0x05191b07, | ||
82 | 0x061a1a06, 0x071b1905, 0x091b1804, 0x0a1c1703, | ||
83 | 0x0b1d1602, 0x0c1d1502, 0x0e1d1401, 0x0f1e1300, | ||
84 | |||
85 | 0x00111e11, 0x00131d10, 0x01141d0e, 0x02151c0d, | ||
86 | 0x03161c0b, 0x04171b0a, 0x05171b09, 0x06181a08, | ||
87 | 0x07191907, 0x081a1806, 0x091a1805, 0x0a1b1704, | ||
88 | 0x0b1c1603, 0x0d1c1502, 0x0e1d1401, 0x0f1d1301, | ||
89 | }; | ||
90 | |||
91 | static int sun8i_ui_scaler_coef_index(unsigned int step) | ||
92 | { | ||
93 | unsigned int scale, int_part, float_part; | ||
94 | |||
95 | scale = step >> (SUN8I_UI_SCALER_SCALE_FRAC - 3); | ||
96 | int_part = scale >> 3; | ||
97 | float_part = scale & 0x7; | ||
98 | |||
99 | switch (int_part) { | ||
100 | case 0: | ||
101 | return 0; | ||
102 | case 1: | ||
103 | return float_part; | ||
104 | case 2: | ||
105 | return 8 + (float_part >> 1); | ||
106 | case 3: | ||
107 | return 12; | ||
108 | case 4: | ||
109 | return 13; | ||
110 | default: | ||
111 | return 14; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | void sun8i_ui_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable) | ||
116 | { | ||
117 | int vi_cnt = mixer->cfg->vi_num; | ||
118 | u32 val; | ||
119 | |||
120 | if (WARN_ON(layer < vi_cnt)) | ||
121 | return; | ||
122 | |||
123 | if (enable) | ||
124 | val = SUN8I_SCALER_GSU_CTRL_EN | | ||
125 | SUN8I_SCALER_GSU_CTRL_COEFF_RDY; | ||
126 | else | ||
127 | val = 0; | ||
128 | |||
129 | regmap_write(mixer->engine.regs, | ||
130 | SUN8I_SCALER_GSU_CTRL(vi_cnt, layer - vi_cnt), val); | ||
131 | } | ||
132 | |||
133 | void sun8i_ui_scaler_setup(struct sun8i_mixer *mixer, int layer, | ||
134 | u32 src_w, u32 src_h, u32 dst_w, u32 dst_h, | ||
135 | u32 hscale, u32 vscale, u32 hphase, u32 vphase) | ||
136 | { | ||
137 | int vi_cnt = mixer->cfg->vi_num; | ||
138 | u32 insize, outsize; | ||
139 | int i, offset; | ||
140 | |||
141 | if (WARN_ON(layer < vi_cnt)) | ||
142 | return; | ||
143 | |||
144 | hphase <<= SUN8I_UI_SCALER_PHASE_FRAC - 16; | ||
145 | vphase <<= SUN8I_UI_SCALER_PHASE_FRAC - 16; | ||
146 | hscale <<= SUN8I_UI_SCALER_SCALE_FRAC - 16; | ||
147 | vscale <<= SUN8I_UI_SCALER_SCALE_FRAC - 16; | ||
148 | |||
149 | insize = SUN8I_UI_SCALER_SIZE(src_w, src_h); | ||
150 | outsize = SUN8I_UI_SCALER_SIZE(dst_w, dst_h); | ||
151 | |||
152 | layer -= vi_cnt; | ||
153 | |||
154 | regmap_write(mixer->engine.regs, | ||
155 | SUN8I_SCALER_GSU_OUTSIZE(vi_cnt, layer), outsize); | ||
156 | regmap_write(mixer->engine.regs, | ||
157 | SUN8I_SCALER_GSU_INSIZE(vi_cnt, layer), insize); | ||
158 | regmap_write(mixer->engine.regs, | ||
159 | SUN8I_SCALER_GSU_HSTEP(vi_cnt, layer), hscale); | ||
160 | regmap_write(mixer->engine.regs, | ||
161 | SUN8I_SCALER_GSU_VSTEP(vi_cnt, layer), vscale); | ||
162 | regmap_write(mixer->engine.regs, | ||
163 | SUN8I_SCALER_GSU_HPHASE(vi_cnt, layer), hphase); | ||
164 | regmap_write(mixer->engine.regs, | ||
165 | SUN8I_SCALER_GSU_VPHASE(vi_cnt, layer), vphase); | ||
166 | offset = sun8i_ui_scaler_coef_index(hscale) * | ||
167 | SUN8I_UI_SCALER_COEFF_COUNT; | ||
168 | for (i = 0; i < SUN8I_UI_SCALER_COEFF_COUNT; i++) | ||
169 | regmap_write(mixer->engine.regs, | ||
170 | SUN8I_SCALER_GSU_HCOEFF(vi_cnt, layer, i), | ||
171 | lan2coefftab16[offset + i]); | ||
172 | } | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_scaler.h b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.h new file mode 100644 index 000000000000..86295be8be78 --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Jernej Skrabec <jernej.skrabec@siol.net> | ||
3 | * | ||
4 | * This file is licensed under the terms of the GNU General Public | ||
5 | * License version 2. This program is licensed "as is" without any | ||
6 | * warranty of any kind, whether express or implied. | ||
7 | */ | ||
8 | |||
9 | #ifndef _SUN8I_UI_SCALER_H_ | ||
10 | #define _SUN8I_UI_SCALER_H_ | ||
11 | |||
12 | #include "sun8i_mixer.h" | ||
13 | |||
14 | /* this two macros assumes 16 fractional bits which is standard in DRM */ | ||
15 | #define SUN8I_UI_SCALER_SCALE_MIN 1 | ||
16 | #define SUN8I_UI_SCALER_SCALE_MAX ((1UL << 20) - 1) | ||
17 | |||
18 | #define SUN8I_UI_SCALER_SCALE_FRAC 20 | ||
19 | #define SUN8I_UI_SCALER_PHASE_FRAC 20 | ||
20 | #define SUN8I_UI_SCALER_COEFF_COUNT 16 | ||
21 | #define SUN8I_UI_SCALER_SIZE(w, h) (((h) - 1) << 16 | ((w) - 1)) | ||
22 | |||
23 | #define SUN8I_SCALER_GSU_CTRL(vi_cnt, ui_idx) \ | ||
24 | (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x0) | ||
25 | #define SUN8I_SCALER_GSU_OUTSIZE(vi_cnt, ui_idx) \ | ||
26 | (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x40) | ||
27 | #define SUN8I_SCALER_GSU_INSIZE(vi_cnt, ui_idx) \ | ||
28 | (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x80) | ||
29 | #define SUN8I_SCALER_GSU_HSTEP(vi_cnt, ui_idx) \ | ||
30 | (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x88) | ||
31 | #define SUN8I_SCALER_GSU_VSTEP(vi_cnt, ui_idx) \ | ||
32 | (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x8c) | ||
33 | #define SUN8I_SCALER_GSU_HPHASE(vi_cnt, ui_idx) \ | ||
34 | (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x90) | ||
35 | #define SUN8I_SCALER_GSU_VPHASE(vi_cnt, ui_idx) \ | ||
36 | (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x98) | ||
37 | #define SUN8I_SCALER_GSU_HCOEFF(vi_cnt, ui_idx, index) \ | ||
38 | (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x200 + \ | ||
39 | 0x4 * (index)) | ||
40 | |||
41 | #define SUN8I_SCALER_GSU_CTRL_EN BIT(0) | ||
42 | #define SUN8I_SCALER_GSU_CTRL_COEFF_RDY BIT(4) | ||
43 | |||
44 | void sun8i_ui_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable); | ||
45 | void sun8i_ui_scaler_setup(struct sun8i_mixer *mixer, int layer, | ||
46 | u32 src_w, u32 src_h, u32 dst_w, u32 dst_h, | ||
47 | u32 hscale, u32 vscale, u32 hphase, u32 vphase); | ||
48 | |||
49 | #endif | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c new file mode 100644 index 000000000000..40c3b303068a --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c | |||
@@ -0,0 +1,390 @@ | |||
1 | /* | ||
2 | * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation; either version 2 of | ||
7 | * the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <drm/drm_atomic.h> | ||
11 | #include <drm/drm_atomic_helper.h> | ||
12 | #include <drm/drm_crtc.h> | ||
13 | #include <drm/drm_crtc_helper.h> | ||
14 | #include <drm/drm_fb_cma_helper.h> | ||
15 | #include <drm/drm_gem_cma_helper.h> | ||
16 | #include <drm/drm_plane_helper.h> | ||
17 | #include <drm/drmP.h> | ||
18 | |||
19 | #include "sun8i_vi_layer.h" | ||
20 | #include "sun8i_mixer.h" | ||
21 | #include "sun8i_vi_scaler.h" | ||
22 | |||
23 | static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel, | ||
24 | int overlay, bool enable) | ||
25 | { | ||
26 | u32 val; | ||
27 | |||
28 | DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n", | ||
29 | enable ? "En" : "Dis", channel, overlay); | ||
30 | |||
31 | if (enable) | ||
32 | val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN; | ||
33 | else | ||
34 | val = 0; | ||
35 | |||
36 | regmap_update_bits(mixer->engine.regs, | ||
37 | SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay), | ||
38 | SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val); | ||
39 | |||
40 | if (enable) | ||
41 | val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel); | ||
42 | else | ||
43 | val = 0; | ||
44 | |||
45 | regmap_update_bits(mixer->engine.regs, | ||
46 | SUN8I_MIXER_BLEND_PIPE_CTL, | ||
47 | SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val); | ||
48 | } | ||
49 | |||
50 | static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, | ||
51 | int overlay, struct drm_plane *plane) | ||
52 | { | ||
53 | struct drm_plane_state *state = plane->state; | ||
54 | const struct drm_format_info *format = state->fb->format; | ||
55 | u32 src_w, src_h, dst_w, dst_h; | ||
56 | u32 outsize, insize; | ||
57 | u32 hphase, vphase; | ||
58 | bool subsampled; | ||
59 | |||
60 | DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n", | ||
61 | channel, overlay); | ||
62 | |||
63 | src_w = drm_rect_width(&state->src) >> 16; | ||
64 | src_h = drm_rect_height(&state->src) >> 16; | ||
65 | dst_w = drm_rect_width(&state->dst); | ||
66 | dst_h = drm_rect_height(&state->dst); | ||
67 | |||
68 | hphase = state->src.x1 & 0xffff; | ||
69 | vphase = state->src.y1 & 0xffff; | ||
70 | |||
71 | /* make coordinates dividable by subsampling factor */ | ||
72 | if (format->hsub > 1) { | ||
73 | int mask, remainder; | ||
74 | |||
75 | mask = format->hsub - 1; | ||
76 | remainder = (state->src.x1 >> 16) & mask; | ||
77 | src_w = (src_w + remainder) & ~mask; | ||
78 | hphase += remainder << 16; | ||
79 | } | ||
80 | |||
81 | if (format->vsub > 1) { | ||
82 | int mask, remainder; | ||
83 | |||
84 | mask = format->vsub - 1; | ||
85 | remainder = (state->src.y1 >> 16) & mask; | ||
86 | src_h = (src_h + remainder) & ~mask; | ||
87 | vphase += remainder << 16; | ||
88 | } | ||
89 | |||
90 | insize = SUN8I_MIXER_SIZE(src_w, src_h); | ||
91 | outsize = SUN8I_MIXER_SIZE(dst_w, dst_h); | ||
92 | |||
93 | /* Set height and width */ | ||
94 | DRM_DEBUG_DRIVER("Layer source offset X: %d Y: %d\n", | ||
95 | (state->src.x1 >> 16) & ~(format->hsub - 1), | ||
96 | (state->src.y1 >> 16) & ~(format->vsub - 1)); | ||
97 | DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h); | ||
98 | regmap_write(mixer->engine.regs, | ||
99 | SUN8I_MIXER_CHAN_VI_LAYER_SIZE(channel, overlay), | ||
100 | insize); | ||
101 | regmap_write(mixer->engine.regs, | ||
102 | SUN8I_MIXER_CHAN_VI_OVL_SIZE(channel), | ||
103 | insize); | ||
104 | |||
105 | /* | ||
106 | * Scaler must be enabled for subsampled formats, so it scales | ||
107 | * chroma to same size as luma. | ||
108 | */ | ||
109 | subsampled = format->hsub > 1 || format->vsub > 1; | ||
110 | |||
111 | if (insize != outsize || subsampled || hphase || vphase) { | ||
112 | u32 hscale, vscale; | ||
113 | |||
114 | DRM_DEBUG_DRIVER("HW scaling is enabled\n"); | ||
115 | |||
116 | hscale = state->src_w / state->crtc_w; | ||
117 | vscale = state->src_h / state->crtc_h; | ||
118 | |||
119 | sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w, | ||
120 | dst_h, hscale, vscale, hphase, vphase, | ||
121 | format); | ||
122 | sun8i_vi_scaler_enable(mixer, channel, true); | ||
123 | } else { | ||
124 | DRM_DEBUG_DRIVER("HW scaling is not needed\n"); | ||
125 | sun8i_vi_scaler_enable(mixer, channel, false); | ||
126 | } | ||
127 | |||
128 | /* Set base coordinates */ | ||
129 | DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n", | ||
130 | state->dst.x1, state->dst.y1); | ||
131 | DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h); | ||
132 | regmap_write(mixer->engine.regs, | ||
133 | SUN8I_MIXER_BLEND_ATTR_COORD(channel), | ||
134 | SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1)); | ||
135 | regmap_write(mixer->engine.regs, | ||
136 | SUN8I_MIXER_BLEND_ATTR_INSIZE(channel), | ||
137 | outsize); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, | ||
143 | int overlay, struct drm_plane *plane) | ||
144 | { | ||
145 | struct drm_plane_state *state = plane->state; | ||
146 | const struct de2_fmt_info *fmt_info; | ||
147 | u32 val; | ||
148 | |||
149 | fmt_info = sun8i_mixer_format_info(state->fb->format->format); | ||
150 | if (!fmt_info) { | ||
151 | DRM_DEBUG_DRIVER("Invalid format\n"); | ||
152 | return -EINVAL; | ||
153 | } | ||
154 | |||
155 | val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET; | ||
156 | regmap_update_bits(mixer->engine.regs, | ||
157 | SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay), | ||
158 | SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val); | ||
159 | |||
160 | if (fmt_info->csc != SUN8I_CSC_MODE_OFF) { | ||
161 | sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_info->csc); | ||
162 | sun8i_csc_enable_ccsc(mixer, channel, true); | ||
163 | } else { | ||
164 | sun8i_csc_enable_ccsc(mixer, channel, false); | ||
165 | } | ||
166 | |||
167 | if (fmt_info->rgb) | ||
168 | val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE; | ||
169 | else | ||
170 | val = 0; | ||
171 | |||
172 | regmap_update_bits(mixer->engine.regs, | ||
173 | SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay), | ||
174 | SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE, val); | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, | ||
180 | int overlay, struct drm_plane *plane) | ||
181 | { | ||
182 | struct drm_plane_state *state = plane->state; | ||
183 | struct drm_framebuffer *fb = state->fb; | ||
184 | const struct drm_format_info *format = fb->format; | ||
185 | struct drm_gem_cma_object *gem; | ||
186 | u32 dx, dy, src_x, src_y; | ||
187 | dma_addr_t paddr; | ||
188 | int i; | ||
189 | |||
190 | /* Adjust x and y to be dividable by subsampling factor */ | ||
191 | src_x = (state->src.x1 >> 16) & ~(format->hsub - 1); | ||
192 | src_y = (state->src.y1 >> 16) & ~(format->vsub - 1); | ||
193 | |||
194 | for (i = 0; i < format->num_planes; i++) { | ||
195 | /* Get the physical address of the buffer in memory */ | ||
196 | gem = drm_fb_cma_get_gem_obj(fb, i); | ||
197 | |||
198 | DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr); | ||
199 | |||
200 | /* Compute the start of the displayed memory */ | ||
201 | paddr = gem->paddr + fb->offsets[i]; | ||
202 | |||
203 | dx = src_x; | ||
204 | dy = src_y; | ||
205 | |||
206 | if (i > 0) { | ||
207 | dx /= format->hsub; | ||
208 | dy /= format->vsub; | ||
209 | } | ||
210 | |||
211 | /* Fixup framebuffer address for src coordinates */ | ||
212 | paddr += dx * format->cpp[i]; | ||
213 | paddr += dy * fb->pitches[i]; | ||
214 | |||
215 | /* Set the line width */ | ||
216 | DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n", | ||
217 | i + 1, fb->pitches[i]); | ||
218 | regmap_write(mixer->engine.regs, | ||
219 | SUN8I_MIXER_CHAN_VI_LAYER_PITCH(channel, | ||
220 | overlay, i), | ||
221 | fb->pitches[i]); | ||
222 | |||
223 | DRM_DEBUG_DRIVER("Setting %d. buffer address to %pad\n", | ||
224 | i + 1, &paddr); | ||
225 | |||
226 | regmap_write(mixer->engine.regs, | ||
227 | SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(channel, | ||
228 | overlay, i), | ||
229 | lower_32_bits(paddr)); | ||
230 | } | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static int sun8i_vi_layer_atomic_check(struct drm_plane *plane, | ||
236 | struct drm_plane_state *state) | ||
237 | { | ||
238 | struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); | ||
239 | struct drm_crtc *crtc = state->crtc; | ||
240 | struct drm_crtc_state *crtc_state; | ||
241 | int min_scale, max_scale; | ||
242 | struct drm_rect clip; | ||
243 | |||
244 | if (!crtc) | ||
245 | return 0; | ||
246 | |||
247 | crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); | ||
248 | if (WARN_ON(!crtc_state)) | ||
249 | return -EINVAL; | ||
250 | |||
251 | clip.x1 = 0; | ||
252 | clip.y1 = 0; | ||
253 | clip.x2 = crtc_state->adjusted_mode.hdisplay; | ||
254 | clip.y2 = crtc_state->adjusted_mode.vdisplay; | ||
255 | |||
256 | min_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
257 | max_scale = DRM_PLANE_HELPER_NO_SCALING; | ||
258 | |||
259 | if (layer->mixer->cfg->scaler_mask & BIT(layer->channel)) { | ||
260 | min_scale = SUN8I_VI_SCALER_SCALE_MIN; | ||
261 | max_scale = SUN8I_VI_SCALER_SCALE_MAX; | ||
262 | } | ||
263 | |||
264 | return drm_atomic_helper_check_plane_state(state, crtc_state, &clip, | ||
265 | min_scale, max_scale, | ||
266 | true, true); | ||
267 | } | ||
268 | |||
269 | static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane, | ||
270 | struct drm_plane_state *old_state) | ||
271 | { | ||
272 | struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); | ||
273 | struct sun8i_mixer *mixer = layer->mixer; | ||
274 | |||
275 | sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false); | ||
276 | } | ||
277 | |||
278 | static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, | ||
279 | struct drm_plane_state *old_state) | ||
280 | { | ||
281 | struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); | ||
282 | struct sun8i_mixer *mixer = layer->mixer; | ||
283 | |||
284 | if (!plane->state->visible) { | ||
285 | sun8i_vi_layer_enable(mixer, layer->channel, | ||
286 | layer->overlay, false); | ||
287 | return; | ||
288 | } | ||
289 | |||
290 | sun8i_vi_layer_update_coord(mixer, layer->channel, | ||
291 | layer->overlay, plane); | ||
292 | sun8i_vi_layer_update_formats(mixer, layer->channel, | ||
293 | layer->overlay, plane); | ||
294 | sun8i_vi_layer_update_buffer(mixer, layer->channel, | ||
295 | layer->overlay, plane); | ||
296 | sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, true); | ||
297 | } | ||
298 | |||
299 | static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { | ||
300 | .atomic_check = sun8i_vi_layer_atomic_check, | ||
301 | .atomic_disable = sun8i_vi_layer_atomic_disable, | ||
302 | .atomic_update = sun8i_vi_layer_atomic_update, | ||
303 | }; | ||
304 | |||
305 | static const struct drm_plane_funcs sun8i_vi_layer_funcs = { | ||
306 | .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, | ||
307 | .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, | ||
308 | .destroy = drm_plane_cleanup, | ||
309 | .disable_plane = drm_atomic_helper_disable_plane, | ||
310 | .reset = drm_atomic_helper_plane_reset, | ||
311 | .update_plane = drm_atomic_helper_update_plane, | ||
312 | }; | ||
313 | |||
314 | /* | ||
315 | * While all RGB formats are supported, VI planes don't support | ||
316 | * alpha blending, so there is no point having formats with alpha | ||
317 | * channel if their opaque analog exist. | ||
318 | */ | ||
319 | static const u32 sun8i_vi_layer_formats[] = { | ||
320 | DRM_FORMAT_ABGR1555, | ||
321 | DRM_FORMAT_ABGR4444, | ||
322 | DRM_FORMAT_ARGB1555, | ||
323 | DRM_FORMAT_ARGB4444, | ||
324 | DRM_FORMAT_BGR565, | ||
325 | DRM_FORMAT_BGR888, | ||
326 | DRM_FORMAT_BGRA5551, | ||
327 | DRM_FORMAT_BGRA4444, | ||
328 | DRM_FORMAT_BGRX8888, | ||
329 | DRM_FORMAT_RGB565, | ||
330 | DRM_FORMAT_RGB888, | ||
331 | DRM_FORMAT_RGBA4444, | ||
332 | DRM_FORMAT_RGBA5551, | ||
333 | DRM_FORMAT_RGBX8888, | ||
334 | DRM_FORMAT_XBGR8888, | ||
335 | DRM_FORMAT_XRGB8888, | ||
336 | |||
337 | DRM_FORMAT_NV16, | ||
338 | DRM_FORMAT_NV12, | ||
339 | DRM_FORMAT_NV21, | ||
340 | DRM_FORMAT_NV61, | ||
341 | DRM_FORMAT_UYVY, | ||
342 | DRM_FORMAT_VYUY, | ||
343 | DRM_FORMAT_YUYV, | ||
344 | DRM_FORMAT_YVYU, | ||
345 | DRM_FORMAT_YUV411, | ||
346 | DRM_FORMAT_YUV420, | ||
347 | DRM_FORMAT_YUV422, | ||
348 | DRM_FORMAT_YUV444, | ||
349 | DRM_FORMAT_YVU411, | ||
350 | DRM_FORMAT_YVU420, | ||
351 | DRM_FORMAT_YVU422, | ||
352 | DRM_FORMAT_YVU444, | ||
353 | }; | ||
354 | |||
355 | struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, | ||
356 | struct sun8i_mixer *mixer, | ||
357 | int index) | ||
358 | { | ||
359 | struct sun8i_vi_layer *layer; | ||
360 | int ret; | ||
361 | |||
362 | layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL); | ||
363 | if (!layer) | ||
364 | return ERR_PTR(-ENOMEM); | ||
365 | |||
366 | /* possible crtcs are set later */ | ||
367 | ret = drm_universal_plane_init(drm, &layer->plane, 0, | ||
368 | &sun8i_vi_layer_funcs, | ||
369 | sun8i_vi_layer_formats, | ||
370 | ARRAY_SIZE(sun8i_vi_layer_formats), | ||
371 | NULL, DRM_PLANE_TYPE_OVERLAY, NULL); | ||
372 | if (ret) { | ||
373 | dev_err(drm->dev, "Couldn't initialize layer\n"); | ||
374 | return ERR_PTR(ret); | ||
375 | } | ||
376 | |||
377 | /* fixed zpos for now */ | ||
378 | ret = drm_plane_create_zpos_immutable_property(&layer->plane, index); | ||
379 | if (ret) { | ||
380 | dev_err(drm->dev, "Couldn't add zpos property\n"); | ||
381 | return ERR_PTR(ret); | ||
382 | } | ||
383 | |||
384 | drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs); | ||
385 | layer->mixer = mixer; | ||
386 | layer->channel = index; | ||
387 | layer->overlay = 0; | ||
388 | |||
389 | return layer; | ||
390 | } | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h new file mode 100644 index 000000000000..6996627a0a76 --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation; either version 2 of | ||
7 | * the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #ifndef _SUN8I_VI_LAYER_H_ | ||
11 | #define _SUN8I_VI_LAYER_H_ | ||
12 | |||
13 | #include <drm/drm_plane.h> | ||
14 | |||
15 | #define SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch, layer) \ | ||
16 | (0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x0) | ||
17 | #define SUN8I_MIXER_CHAN_VI_LAYER_SIZE(ch, layer) \ | ||
18 | (0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x4) | ||
19 | #define SUN8I_MIXER_CHAN_VI_LAYER_COORD(ch, layer) \ | ||
20 | (0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x8) | ||
21 | #define SUN8I_MIXER_CHAN_VI_LAYER_PITCH(ch, layer, plane) \ | ||
22 | (0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0xc + 4 * (plane)) | ||
23 | #define SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(ch, layer, plane) \ | ||
24 | (0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x18 + 4 * (plane)) | ||
25 | #define SUN8I_MIXER_CHAN_VI_OVL_SIZE(ch) (0x2000 + 0x1000 * (ch) + 0xe8) | ||
26 | |||
27 | #define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN BIT(0) | ||
28 | /* RGB mode should be set for RGB formats and cleared for YCbCr */ | ||
29 | #define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE BIT(15) | ||
30 | #define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET 8 | ||
31 | #define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK GENMASK(12, 8) | ||
32 | |||
33 | struct sun8i_mixer; | ||
34 | |||
35 | struct sun8i_vi_layer { | ||
36 | struct drm_plane plane; | ||
37 | struct sun8i_mixer *mixer; | ||
38 | int channel; | ||
39 | int overlay; | ||
40 | }; | ||
41 | |||
42 | static inline struct sun8i_vi_layer * | ||
43 | plane_to_sun8i_vi_layer(struct drm_plane *plane) | ||
44 | { | ||
45 | return container_of(plane, struct sun8i_vi_layer, plane); | ||
46 | } | ||
47 | |||
48 | struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, | ||
49 | struct sun8i_mixer *mixer, | ||
50 | int index); | ||
51 | #endif /* _SUN8I_VI_LAYER_H_ */ | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c new file mode 100644 index 000000000000..d3f1acb234b7 --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | |||
@@ -0,0 +1,971 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Jernej Skrabec <jernej.skrabec@siol.net> | ||
3 | * | ||
4 | * Coefficients are taken from BSP driver, which is: | ||
5 | * Copyright (C) 2014-2015 Allwinner | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include "sun8i_vi_scaler.h" | ||
13 | |||
14 | static const u32 lan3coefftab32_left[480] = { | ||
15 | 0x40000000, 0x40fe0000, 0x3ffd0100, 0x3efc0100, | ||
16 | 0x3efb0100, 0x3dfa0200, 0x3cf90200, 0x3bf80200, | ||
17 | 0x39f70200, 0x37f70200, 0x35f70200, 0x33f70200, | ||
18 | 0x31f70200, 0x2ef70200, 0x2cf70200, 0x2af70200, | ||
19 | 0x27f70200, 0x24f80100, 0x22f80100, 0x1ef90100, | ||
20 | 0x1cf90100, 0x19fa0100, 0x17fa0100, 0x14fb0100, | ||
21 | 0x11fc0000, 0x0ffc0000, 0x0cfd0000, 0x0afd0000, | ||
22 | 0x08fe0000, 0x05ff0000, 0x03ff0000, 0x02000000, | ||
23 | |||
24 | 0x3806fc02, 0x3805fc02, 0x3803fd01, 0x3801fe01, | ||
25 | 0x3700fe01, 0x35ffff01, 0x35fdff01, 0x34fc0001, | ||
26 | 0x34fb0000, 0x33fa0000, 0x31fa0100, 0x2ff90100, | ||
27 | 0x2df80200, 0x2bf80200, 0x2af70200, 0x28f70200, | ||
28 | 0x27f70200, 0x24f70300, 0x22f70300, 0x1ff70300, | ||
29 | 0x1ef70300, 0x1cf70300, 0x1af70300, 0x18f70300, | ||
30 | 0x16f80300, 0x13f80300, 0x11f90300, 0x0ef90300, | ||
31 | 0x0efa0200, 0x0cfa0200, 0x0afb0200, 0x08fb0200, | ||
32 | |||
33 | 0x320bfa02, 0x3309fa02, 0x3208fb02, 0x3206fb02, | ||
34 | 0x3205fb02, 0x3104fc02, 0x3102fc01, 0x3001fd01, | ||
35 | 0x3000fd01, 0x2ffffd01, 0x2efefe01, 0x2dfdfe01, | ||
36 | 0x2bfcff01, 0x29fcff01, 0x28fbff01, 0x27fa0001, | ||
37 | 0x26fa0000, 0x24f90000, 0x22f90100, 0x20f90100, | ||
38 | 0x1ff80100, 0x1ef80100, 0x1cf80100, 0x1af80200, | ||
39 | 0x18f80200, 0x17f80200, 0x15f80200, 0x12f80200, | ||
40 | 0x11f90200, 0x0ff90200, 0x0df90200, 0x0cfa0200, | ||
41 | |||
42 | 0x2e0efa01, 0x2f0dfa01, 0x2f0bfa01, 0x2e0afa01, | ||
43 | 0x2e09fa01, 0x2e07fb01, 0x2d06fb01, 0x2d05fb01, | ||
44 | 0x2c04fb01, 0x2b03fc01, 0x2a02fc01, 0x2a01fc01, | ||
45 | 0x2800fd01, 0x28fffd01, 0x26fefd01, 0x25fefe01, | ||
46 | 0x24fdfe01, 0x23fcfe01, 0x21fcff01, 0x20fbff01, | ||
47 | 0x1efbff01, 0x1efbff00, 0x1cfa0000, 0x1bfa0000, | ||
48 | 0x19fa0000, 0x18fa0000, 0x17f90000, 0x15f90100, | ||
49 | 0x14f90100, 0x12f90100, 0x11f90100, 0x0ff90100, | ||
50 | |||
51 | 0x2b10fa00, 0x2b0ffa00, 0x2b0efa00, 0x2b0cfa00, | ||
52 | 0x2b0bfa00, 0x2a0afb01, 0x2a09fb01, 0x2908fb01, | ||
53 | 0x2807fb01, 0x2806fb01, 0x2805fb01, 0x2604fc01, | ||
54 | 0x2503fc01, 0x2502fc01, 0x2401fc01, 0x2301fc01, | ||
55 | 0x2100fd01, 0x21fffd01, 0x21fffd01, 0x20fefd01, | ||
56 | 0x1dfefe01, 0x1cfdfe01, 0x1cfdfe00, 0x1bfcfe00, | ||
57 | 0x19fcff00, 0x19fbff00, 0x17fbff00, 0x16fbff00, | ||
58 | 0x15fbff00, 0x14fb0000, 0x13fa0000, 0x11fa0000, | ||
59 | |||
60 | 0x2811fcff, 0x2810fcff, 0x280ffbff, 0x280efbff, | ||
61 | 0x270dfb00, 0x270cfb00, 0x270bfb00, 0x260afb00, | ||
62 | 0x2609fb00, 0x2508fb00, 0x2507fb00, 0x2407fb00, | ||
63 | 0x2406fc00, 0x2305fc00, 0x2204fc00, 0x2203fc00, | ||
64 | 0x2103fc00, 0x2002fc00, 0x1f01fd00, 0x1e01fd00, | ||
65 | 0x1d00fd00, 0x1dfffd00, 0x1cfffd00, 0x1bfefd00, | ||
66 | 0x1afefe00, 0x19fefe00, 0x18fdfe00, 0x17fdfe00, | ||
67 | 0x16fdfe00, 0x15fcff00, 0x13fcff00, 0x12fcff00, | ||
68 | |||
69 | 0x2512fdfe, 0x2511fdff, 0x2410fdff, 0x240ffdff, | ||
70 | 0x240efcff, 0x240dfcff, 0x240dfcff, 0x240cfcff, | ||
71 | 0x230bfcff, 0x230afc00, 0x2209fc00, 0x2108fc00, | ||
72 | 0x2108fc00, 0x2007fc00, 0x2006fc00, 0x2005fc00, | ||
73 | 0x1f05fc00, 0x1e04fc00, 0x1e03fc00, 0x1c03fd00, | ||
74 | 0x1c02fd00, 0x1b02fd00, 0x1b01fd00, 0x1a00fd00, | ||
75 | 0x1900fd00, 0x1800fd00, 0x17fffe00, 0x16fffe00, | ||
76 | 0x16fefe00, 0x14fefe00, 0x13fefe00, 0x13fdfe00, | ||
77 | |||
78 | 0x2212fffe, 0x2211fefe, 0x2211fefe, 0x2110fefe, | ||
79 | 0x210ffeff, 0x220efdff, 0x210dfdff, 0x210dfdff, | ||
80 | 0x210cfdff, 0x210bfdff, 0x200afdff, 0x200afdff, | ||
81 | 0x1f09fdff, 0x1f08fdff, 0x1d08fd00, 0x1c07fd00, | ||
82 | 0x1d06fd00, 0x1b06fd00, 0x1b05fd00, 0x1c04fd00, | ||
83 | 0x1b04fd00, 0x1a03fd00, 0x1a03fd00, 0x1902fd00, | ||
84 | 0x1802fd00, 0x1801fd00, 0x1701fd00, 0x1600fd00, | ||
85 | 0x1400fe00, 0x1400fe00, 0x14fffe00, 0x13fffe00, | ||
86 | |||
87 | 0x201200fe, 0x201100fe, 0x1f11fffe, 0x2010fffe, | ||
88 | 0x1f0ffffe, 0x1e0ffffe, 0x1f0efeff, 0x1f0dfeff, | ||
89 | 0x1f0dfeff, 0x1e0cfeff, 0x1e0bfeff, 0x1d0bfeff, | ||
90 | 0x1d0afeff, 0x1d09fdff, 0x1d09fdff, 0x1c08fdff, | ||
91 | 0x1c07fdff, 0x1b07fd00, 0x1b06fd00, 0x1a06fd00, | ||
92 | 0x1a05fd00, 0x1805fd00, 0x1904fd00, 0x1804fd00, | ||
93 | 0x1703fd00, 0x1703fd00, 0x1602fe00, 0x1502fe00, | ||
94 | 0x1501fe00, 0x1401fe00, 0x1301fe00, 0x1300fe00, | ||
95 | |||
96 | 0x1c1202fe, 0x1c1102fe, 0x1b1102fe, 0x1c1001fe, | ||
97 | 0x1b1001fe, 0x1b0f01ff, 0x1b0e00ff, 0x1b0e00ff, | ||
98 | 0x1b0d00ff, 0x1a0d00ff, 0x1a0c00ff, 0x1a0cffff, | ||
99 | 0x1a0bffff, 0x1a0bffff, 0x1a0affff, 0x180affff, | ||
100 | 0x1909ffff, 0x1809ffff, 0x1808ffff, 0x1808feff, | ||
101 | 0x1807feff, 0x1707fe00, 0x1606fe00, 0x1506fe00, | ||
102 | 0x1605fe00, 0x1505fe00, 0x1504fe00, 0x1304fe00, | ||
103 | 0x1304fe00, 0x1303fe00, 0x1203fe00, 0x1203fe00, | ||
104 | |||
105 | 0x181104ff, 0x191103ff, 0x191003ff, 0x181003ff, | ||
106 | 0x180f03ff, 0x190f02ff, 0x190e02ff, 0x180e02ff, | ||
107 | 0x180d02ff, 0x180d01ff, 0x180d01ff, 0x180c01ff, | ||
108 | 0x180c01ff, 0x180b00ff, 0x170b00ff, 0x170a00ff, | ||
109 | 0x170a00ff, 0x170900ff, 0x160900ff, 0x160900ff, | ||
110 | 0x1608ffff, 0x1508ffff, 0x1507ff00, 0x1507ff00, | ||
111 | 0x1407ff00, 0x1306ff00, 0x1306ff00, 0x1305ff00, | ||
112 | 0x1205ff00, 0x1105ff00, 0x1204ff00, 0x1104ff00, | ||
113 | |||
114 | 0x171005ff, 0x171005ff, 0x171004ff, 0x170f04ff, | ||
115 | 0x160f04ff, 0x170f03ff, 0x170e03ff, 0x160e03ff, | ||
116 | 0x160d03ff, 0x160d02ff, 0x160d02ff, 0x160c02ff, | ||
117 | 0x160c02ff, 0x160c02ff, 0x160b01ff, 0x150b01ff, | ||
118 | 0x150a01ff, 0x150a01ff, 0x150a01ff, 0x140901ff, | ||
119 | 0x14090000, 0x14090000, 0x14080000, 0x13080000, | ||
120 | 0x13070000, 0x12070000, 0x12070000, 0x12060000, | ||
121 | 0x11060000, 0x11060000, 0x11050000, 0x1105ff00, | ||
122 | |||
123 | 0x14100600, 0x15100500, 0x150f0500, 0x150f0500, | ||
124 | 0x140f0500, 0x150e0400, 0x140e0400, 0x130e0400, | ||
125 | 0x140d0400, 0x150d0300, 0x130d0300, 0x140c0300, | ||
126 | 0x140c0300, 0x140c0200, 0x140b0200, 0x130b0200, | ||
127 | 0x120b0200, 0x130a0200, 0x130a0200, 0x130a0100, | ||
128 | 0x13090100, 0x12090100, 0x11090100, 0x12080100, | ||
129 | 0x11080100, 0x10080100, 0x11070100, 0x11070000, | ||
130 | 0x10070000, 0x11060000, 0x10060000, 0x10060000, | ||
131 | |||
132 | 0x140f0600, 0x140f0600, 0x130f0600, 0x140f0500, | ||
133 | 0x140e0500, 0x130e0500, 0x130e0500, 0x140d0400, | ||
134 | 0x140d0400, 0x130d0400, 0x120d0400, 0x130c0400, | ||
135 | 0x130c0300, 0x130c0300, 0x130b0300, 0x130b0300, | ||
136 | 0x110b0300, 0x130a0200, 0x120a0200, 0x120a0200, | ||
137 | 0x120a0200, 0x12090200, 0x10090200, 0x11090100, | ||
138 | 0x11080100, 0x11080100, 0x10080100, 0x10080100, | ||
139 | 0x10070100, 0x10070100, 0x0f070100, 0x10060100, | ||
140 | |||
141 | 0x120f0701, 0x130f0601, 0x130e0601, 0x130e0601, | ||
142 | 0x120e0601, 0x130e0501, 0x130e0500, 0x130d0500, | ||
143 | 0x120d0500, 0x120d0500, 0x130c0400, 0x130c0400, | ||
144 | 0x120c0400, 0x110c0400, 0x120b0400, 0x120b0300, | ||
145 | 0x120b0300, 0x120b0300, 0x120a0300, 0x110a0300, | ||
146 | 0x110a0200, 0x11090200, 0x11090200, 0x10090200, | ||
147 | 0x10090200, 0x10080200, 0x10080200, 0x10080100, | ||
148 | 0x0f080100, 0x10070100, 0x0f070100, 0x0f070100 | ||
149 | }; | ||
150 | |||
151 | static const u32 lan3coefftab32_right[480] = { | ||
152 | 0x00000000, 0x00000002, 0x0000ff04, 0x0000ff06, | ||
153 | 0x0000fe08, 0x0000fd0a, 0x0000fd0c, 0x0000fc0f, | ||
154 | 0x0000fc12, 0x0001fb14, 0x0001fa17, 0x0001fa19, | ||
155 | 0x0001f91c, 0x0001f91f, 0x0001f822, 0x0001f824, | ||
156 | 0x0002f727, 0x0002f72a, 0x0002f72c, 0x0002f72f, | ||
157 | 0x0002f731, 0x0002f733, 0x0002f735, 0x0002f737, | ||
158 | 0x0002f73a, 0x0002f83b, 0x0002f93c, 0x0002fa3d, | ||
159 | 0x0001fb3e, 0x0001fc3f, 0x0001fd40, 0x0000fe40, | ||
160 | |||
161 | 0x0002fc06, 0x0002fb08, 0x0002fb0a, 0x0002fa0c, | ||
162 | 0x0002fa0e, 0x0003f910, 0x0003f912, 0x0003f814, | ||
163 | 0x0003f816, 0x0003f719, 0x0003f71a, 0x0003f71d, | ||
164 | 0x0003f71f, 0x0003f721, 0x0003f723, 0x0003f725, | ||
165 | 0x0002f727, 0x0002f729, 0x0002f72b, 0x0002f82d, | ||
166 | 0x0002f82e, 0x0001f930, 0x0001fa31, 0x0000fa34, | ||
167 | 0x0000fb34, 0x0100fc35, 0x01fffd36, 0x01ffff37, | ||
168 | 0x01fe0037, 0x01fe0138, 0x01fd0338, 0x02fc0538, | ||
169 | |||
170 | 0x0002fa0b, 0x0002fa0c, 0x0002f90e, 0x0002f910, | ||
171 | 0x0002f911, 0x0002f813, 0x0002f816, 0x0002f817, | ||
172 | 0x0002f818, 0x0002f81a, 0x0001f81c, 0x0001f81e, | ||
173 | 0x0001f820, 0x0001f921, 0x0001f923, 0x0000f925, | ||
174 | 0x0000fa26, 0x0100fa28, 0x01fffb29, 0x01fffc2a, | ||
175 | 0x01fffc2c, 0x01fefd2d, 0x01fefe2e, 0x01fdff2f, | ||
176 | 0x01fd0030, 0x01fd0130, 0x01fc0232, 0x02fc0432, | ||
177 | 0x02fb0532, 0x02fb0633, 0x02fb0833, 0x02fa0933, | ||
178 | |||
179 | 0x0001fa0e, 0x0001f90f, 0x0001f911, 0x0001f913, | ||
180 | 0x0001f914, 0x0001f915, 0x0000f918, 0x0000fa18, | ||
181 | 0x0000fa1a, 0x0000fa1b, 0x0000fa1d, 0x00fffb1e, | ||
182 | 0x01fffb1f, 0x01fffb20, 0x01fffc22, 0x01fefc23, | ||
183 | 0x01fefd24, 0x01fefe25, 0x01fdfe27, 0x01fdff28, | ||
184 | 0x01fd0029, 0x01fc012a, 0x01fc022b, 0x01fc032b, | ||
185 | 0x01fb042d, 0x01fb052d, 0x01fb062e, 0x01fb072e, | ||
186 | 0x01fa092e, 0x01fa0a2f, 0x01fa0b2f, 0x01fa0d2f, | ||
187 | |||
188 | 0x0000fa11, 0x0000fa12, 0x0000fa13, 0x0000fb14, | ||
189 | 0x00fffb16, 0x00fffb16, 0x00fffb17, 0x00fffb19, | ||
190 | 0x00fffc1a, 0x00fefc1c, 0x00fefd1c, 0x01fefd1d, | ||
191 | 0x01fefe1e, 0x01fdfe20, 0x01fdff21, 0x01fdff22, | ||
192 | 0x01fd0023, 0x01fc0124, 0x01fc0124, 0x01fc0225, | ||
193 | 0x01fc0326, 0x01fc0427, 0x01fb0528, 0x01fb0629, | ||
194 | 0x01fb0729, 0x01fb0829, 0x01fb092a, 0x01fb0a2a, | ||
195 | 0x00fa0b2c, 0x00fa0c2b, 0x00fa0e2b, 0x00fa0f2c, | ||
196 | |||
197 | 0x00fffc11, 0x00fffc12, 0x00fffc14, 0x00fffc15, | ||
198 | 0x00fefd16, 0x00fefd17, 0x00fefd18, 0x00fefe19, | ||
199 | 0x00fefe1a, 0x00fdfe1d, 0x00fdff1d, 0x00fdff1e, | ||
200 | 0x00fd001d, 0x00fd011e, 0x00fd0120, 0x00fc0221, | ||
201 | 0x00fc0321, 0x00fc0323, 0x00fc0423, 0x00fc0523, | ||
202 | 0x00fc0624, 0x00fb0725, 0x00fb0726, 0x00fb0827, | ||
203 | 0x00fb0926, 0x00fb0a26, 0x00fb0b27, 0x00fb0c27, | ||
204 | 0x00fb0d27, 0xfffb0e28, 0xfffb0f29, 0xfffc1028, | ||
205 | |||
206 | 0x00fefd13, 0x00fefd13, 0x00fefe14, 0x00fefe15, | ||
207 | 0x00fefe17, 0x00feff17, 0x00feff17, 0x00fd0018, | ||
208 | 0x00fd001a, 0x00fd001a, 0x00fd011b, 0x00fd021c, | ||
209 | 0x00fd021c, 0x00fd031d, 0x00fc031f, 0x00fc041f, | ||
210 | 0x00fc051f, 0x00fc0521, 0x00fc0621, 0x00fc0721, | ||
211 | 0x00fc0821, 0x00fc0822, 0x00fc0922, 0x00fc0a23, | ||
212 | 0xfffc0b24, 0xfffc0c24, 0xfffc0d24, 0xfffc0d25, | ||
213 | 0xfffc0e25, 0xfffd0f25, 0xfffd1025, 0xfffd1125, | ||
214 | |||
215 | 0x00feff12, 0x00feff14, 0x00feff14, 0x00fe0015, | ||
216 | 0x00fe0015, 0x00fd0017, 0x00fd0118, 0x00fd0118, | ||
217 | 0x00fd0218, 0x00fd0219, 0x00fd031a, 0x00fd031a, | ||
218 | 0x00fd041b, 0x00fd041c, 0x00fd051c, 0x00fd061d, | ||
219 | 0x00fd061d, 0x00fd071e, 0x00fd081e, 0xfffd081f, | ||
220 | 0xfffd091f, 0xfffd0a20, 0xfffd0a20, 0xfffd0b21, | ||
221 | 0xfffd0c21, 0xfffd0d21, 0xfffd0d22, 0xfffd0e23, | ||
222 | 0xfffe0f22, 0xfefe1022, 0xfefe1122, 0xfefe1123, | ||
223 | |||
224 | 0x00fe0012, 0x00fe0013, 0x00fe0114, 0x00fe0114, | ||
225 | 0x00fe0116, 0x00fe0216, 0x00fe0216, 0x00fd0317, | ||
226 | 0x00fd0317, 0x00fd0418, 0x00fd0419, 0x00fd0519, | ||
227 | 0x00fd051a, 0x00fd061b, 0x00fd061b, 0x00fd071c, | ||
228 | 0xfffd071e, 0xfffd081d, 0xfffd091d, 0xfffd091e, | ||
229 | 0xfffe0a1d, 0xfffe0b1e, 0xfffe0b1e, 0xfffe0c1e, | ||
230 | 0xfffe0d1f, 0xfffe0d1f, 0xfffe0e1f, 0xfeff0f1f, | ||
231 | 0xfeff0f20, 0xfeff1020, 0xfeff1120, 0xfe001120, | ||
232 | |||
233 | 0x00fe0212, 0x00fe0312, 0x00fe0313, 0x00fe0314, | ||
234 | 0x00fe0414, 0x00fe0414, 0x00fe0416, 0x00fe0515, | ||
235 | 0x00fe0516, 0x00fe0616, 0x00fe0617, 0x00fe0717, | ||
236 | 0xfffe0719, 0xfffe0818, 0xffff0818, 0xffff0919, | ||
237 | 0xffff0919, 0xffff0a19, 0xffff0a1a, 0xffff0b1a, | ||
238 | 0xffff0b1b, 0xffff0c1a, 0xff000c1b, 0xff000d1b, | ||
239 | 0xff000d1b, 0xff000e1b, 0xff000e1c, 0xff010f1c, | ||
240 | 0xfe01101c, 0xfe01101d, 0xfe02111c, 0xfe02111c, | ||
241 | |||
242 | 0x00ff0411, 0x00ff0411, 0x00ff0412, 0x00ff0512, | ||
243 | 0x00ff0513, 0x00ff0513, 0x00ff0613, 0x00ff0614, | ||
244 | 0x00ff0714, 0x00ff0715, 0x00ff0715, 0xffff0816, | ||
245 | 0xffff0816, 0xff000916, 0xff000917, 0xff000918, | ||
246 | 0xff000a17, 0xff000a18, 0xff000b18, 0xff000b18, | ||
247 | 0xff010c18, 0xff010c19, 0xff010d18, 0xff010d18, | ||
248 | 0xff020d18, 0xff020e19, 0xff020e19, 0xff020f19, | ||
249 | 0xff030f19, 0xff031019, 0xff031019, 0xff031119, | ||
250 | |||
251 | 0x00ff0511, 0x00ff0511, 0x00000511, 0x00000611, | ||
252 | 0x00000612, 0x00000612, 0x00000712, 0x00000713, | ||
253 | 0x00000714, 0x00000814, 0x00000814, 0x00000914, | ||
254 | 0x00000914, 0xff010914, 0xff010a15, 0xff010a16, | ||
255 | 0xff010a17, 0xff010b16, 0xff010b16, 0xff020c16, | ||
256 | 0xff020c16, 0xff020c16, 0xff020d16, 0xff020d17, | ||
257 | 0xff030d17, 0xff030e17, 0xff030e17, 0xff030f17, | ||
258 | 0xff040f17, 0xff040f17, 0xff041017, 0xff051017, | ||
259 | |||
260 | 0x00000610, 0x00000610, 0x00000611, 0x00000611, | ||
261 | 0x00000711, 0x00000712, 0x00010712, 0x00010812, | ||
262 | 0x00010812, 0x00010812, 0x00010913, 0x00010913, | ||
263 | 0x00010913, 0x00010a13, 0x00020a13, 0x00020a14, | ||
264 | 0x00020b14, 0x00020b14, 0x00020b14, 0x00020c14, | ||
265 | 0x00030c14, 0x00030c15, 0x00030d15, 0x00030d15, | ||
266 | 0x00040d15, 0x00040e15, 0x00040e15, 0x00040e16, | ||
267 | 0x00050f15, 0x00050f15, 0x00050f16, 0x00051015, | ||
268 | |||
269 | 0x00000611, 0x00010610, 0x00010710, 0x00010710, | ||
270 | 0x00010711, 0x00010811, 0x00010811, 0x00010812, | ||
271 | 0x00010812, 0x00010912, 0x00020912, 0x00020912, | ||
272 | 0x00020a12, 0x00020a12, 0x00020a13, 0x00020a13, | ||
273 | 0x00030b13, 0x00030b13, 0x00030b14, 0x00030c13, | ||
274 | 0x00030c13, 0x00040c13, 0x00040d14, 0x00040d14, | ||
275 | 0x00040d15, 0x00040d15, 0x00050e14, 0x00050e14, | ||
276 | 0x00050e15, 0x00050f14, 0x00060f14, 0x00060f14, | ||
277 | |||
278 | 0x0001070f, 0x0001070f, 0x00010710, 0x00010710, | ||
279 | 0x00010810, 0x00010810, 0x00020810, 0x00020811, | ||
280 | 0x00020911, 0x00020911, 0x00020912, 0x00020912, | ||
281 | 0x00020a12, 0x00030a12, 0x00030a12, 0x00030b12, | ||
282 | 0x00030b12, 0x00030b12, 0x00040b12, 0x00040c12, | ||
283 | 0x00040c13, 0x00040c14, 0x00040c14, 0x00050d13, | ||
284 | 0x00050d13, 0x00050d14, 0x00050e13, 0x01050e13, | ||
285 | 0x01060e13, 0x01060e13, 0x01060e14, 0x01060f13 | ||
286 | }; | ||
287 | |||
288 | static const u32 lan2coefftab32[480] = { | ||
289 | 0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd, | ||
290 | 0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb, | ||
291 | 0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb, | ||
292 | 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc, | ||
293 | 0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd, | ||
294 | 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff, | ||
295 | 0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff, | ||
296 | 0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100, | ||
297 | |||
298 | 0xff053804, 0xff063803, 0xff083801, 0xff093701, | ||
299 | 0xff0a3700, 0xff0c3500, 0xff0e34ff, 0xff1033fe, | ||
300 | 0xff1232fd, 0xfe1431fd, 0xfe162ffd, 0xfe182dfd, | ||
301 | 0xfd1b2cfc, 0xfd1d2afc, 0xfd1f28fc, 0xfd2126fc, | ||
302 | 0xfd2323fd, 0xfc2621fd, 0xfc281ffd, 0xfc2a1dfd, | ||
303 | 0xfc2c1bfd, 0xfd2d18fe, 0xfd2f16fe, 0xfd3114fe, | ||
304 | 0xfd3212ff, 0xfe3310ff, 0xff340eff, 0x00350cff, | ||
305 | 0x00360a00, 0x01360900, 0x02370700, 0x03370600, | ||
306 | |||
307 | 0xff083207, 0xff093206, 0xff0a3205, 0xff0c3203, | ||
308 | 0xff0d3103, 0xff0e3102, 0xfe113001, 0xfe132f00, | ||
309 | 0xfe142e00, 0xfe162dff, 0xfe182bff, 0xfe192aff, | ||
310 | 0xfe1b29fe, 0xfe1d27fe, 0xfe1f25fe, 0xfd2124fe, | ||
311 | 0xfe2222fe, 0xfe2421fd, 0xfe251ffe, 0xfe271dfe, | ||
312 | 0xfe291bfe, 0xff2a19fe, 0xff2b18fe, 0xff2d16fe, | ||
313 | 0x002e14fe, 0x002f12ff, 0x013010ff, 0x02300fff, | ||
314 | 0x03310dff, 0x04310cff, 0x05310a00, 0x06310900, | ||
315 | |||
316 | 0xff0a2e09, 0xff0b2e08, 0xff0c2e07, 0xff0e2d06, | ||
317 | 0xff0f2d05, 0xff102d04, 0xff122c03, 0xfe142c02, | ||
318 | 0xfe152b02, 0xfe172a01, 0xfe182901, 0xfe1a2800, | ||
319 | 0xfe1b2700, 0xfe1d2500, 0xff1e24ff, 0xfe2023ff, | ||
320 | 0xff2121ff, 0xff2320fe, 0xff241eff, 0x00251dfe, | ||
321 | 0x00261bff, 0x00281afe, 0x012818ff, 0x012a16ff, | ||
322 | 0x022a15ff, 0x032b13ff, 0x032c12ff, 0x052c10ff, | ||
323 | 0x052d0fff, 0x062d0d00, 0x072d0c00, 0x082d0b00, | ||
324 | |||
325 | 0xff0c2a0b, 0xff0d2a0a, 0xff0e2a09, 0xff0f2a08, | ||
326 | 0xff102a07, 0xff112a06, 0xff132905, 0xff142904, | ||
327 | 0xff162803, 0xff172703, 0xff182702, 0xff1a2601, | ||
328 | 0xff1b2501, 0xff1c2401, 0xff1e2300, 0xff1f2200, | ||
329 | 0x00202000, 0x00211f00, 0x01221d00, 0x01231c00, | ||
330 | 0x01251bff, 0x02251aff, 0x032618ff, 0x032717ff, | ||
331 | 0x042815ff, 0x052814ff, 0x052913ff, 0x06291100, | ||
332 | 0x072a10ff, 0x082a0e00, 0x092a0d00, 0x0a2a0c00, | ||
333 | |||
334 | 0xff0d280c, 0xff0e280b, 0xff0f280a, 0xff102809, | ||
335 | 0xff112808, 0xff122708, 0xff142706, 0xff152705, | ||
336 | 0xff162605, 0xff172604, 0xff192503, 0xff1a2403, | ||
337 | 0x001b2302, 0x001c2202, 0x001d2201, 0x001e2101, | ||
338 | 0x011f1f01, 0x01211e00, 0x01221d00, 0x02221c00, | ||
339 | 0x02231b00, 0x03241900, 0x04241800, 0x04251700, | ||
340 | 0x052616ff, 0x06261400, 0x072713ff, 0x08271100, | ||
341 | 0x08271100, 0x09271000, 0x0a280e00, 0x0b280d00, | ||
342 | |||
343 | 0xff0e260d, 0xff0f260c, 0xff10260b, 0xff11260a, | ||
344 | 0xff122609, 0xff132608, 0xff142508, 0xff152507, | ||
345 | 0x00152506, 0x00172405, 0x00182305, 0x00192304, | ||
346 | 0x001b2203, 0x001c2103, 0x011d2002, 0x011d2002, | ||
347 | 0x011f1f01, 0x021f1e01, 0x02201d01, 0x03211c00, | ||
348 | 0x03221b00, 0x04221a00, 0x04231801, 0x05241700, | ||
349 | 0x06241600, 0x07241500, 0x08251300, 0x09251200, | ||
350 | 0x09261100, 0x0a261000, 0x0b260f00, 0x0c260e00, | ||
351 | |||
352 | 0xff0e250e, 0xff0f250d, 0xff10250c, 0xff11250b, | ||
353 | 0x0011250a, 0x00132409, 0x00142408, 0x00152407, | ||
354 | 0x00162307, 0x00172306, 0x00182206, 0x00192205, | ||
355 | 0x011a2104, 0x011b2004, 0x011c2003, 0x021c1f03, | ||
356 | 0x021e1e02, 0x031e1d02, 0x03201c01, 0x04201b01, | ||
357 | 0x04211a01, 0x05221900, 0x05221801, 0x06231700, | ||
358 | 0x07231600, 0x07241500, 0x08241400, 0x09241300, | ||
359 | 0x0a241200, 0x0b241100, 0x0c241000, 0x0d240f00, | ||
360 | |||
361 | 0x000e240e, 0x000f240d, 0x0010240c, 0x0011240b, | ||
362 | 0x0013230a, 0x0013230a, 0x00142309, 0x00152308, | ||
363 | 0x00162208, 0x00172207, 0x01182106, 0x01192105, | ||
364 | 0x011a2005, 0x021b1f04, 0x021b1f04, 0x021d1e03, | ||
365 | 0x031d1d03, 0x031e1d02, 0x041e1c02, 0x041f1b02, | ||
366 | 0x05201a01, 0x05211901, 0x06211801, 0x07221700, | ||
367 | 0x07221601, 0x08231500, 0x09231400, 0x0a231300, | ||
368 | 0x0a231300, 0x0b231200, 0x0c231100, 0x0d231000, | ||
369 | |||
370 | 0x000f220f, 0x0010220e, 0x0011220d, 0x0012220c, | ||
371 | 0x0013220b, 0x0013220b, 0x0015210a, 0x0015210a, | ||
372 | 0x01162108, 0x01172008, 0x01182007, 0x02191f06, | ||
373 | 0x02191f06, 0x021a1e06, 0x031a1e05, 0x031c1d04, | ||
374 | 0x041c1c04, 0x041d1c03, 0x051d1b03, 0x051e1a03, | ||
375 | 0x061f1902, 0x061f1902, 0x07201801, 0x08201701, | ||
376 | 0x08211601, 0x09211501, 0x0a211500, 0x0b211400, | ||
377 | 0x0b221300, 0x0c221200, 0x0d221100, 0x0e221000, | ||
378 | |||
379 | 0x0010210f, 0x0011210e, 0x0011210e, 0x0012210d, | ||
380 | 0x0013210c, 0x0014200c, 0x0114200b, 0x0115200a, | ||
381 | 0x01161f0a, 0x01171f09, 0x02171f08, 0x02181e08, | ||
382 | 0x03181e07, 0x031a1d06, 0x031a1d06, 0x041b1c05, | ||
383 | 0x041c1c04, 0x051c1b04, 0x051d1a04, 0x061d1a03, | ||
384 | 0x071d1903, 0x071e1803, 0x081e1802, 0x081f1702, | ||
385 | 0x091f1602, 0x0a201501, 0x0b1f1501, 0x0b201401, | ||
386 | 0x0c211300, 0x0d211200, 0x0e201200, 0x0e211100, | ||
387 | |||
388 | 0x00102010, 0x0011200f, 0x0012200e, 0x0013200d, | ||
389 | 0x0013200d, 0x01141f0c, 0x01151f0b, 0x01151f0b, | ||
390 | 0x01161f0a, 0x02171e09, 0x02171e09, 0x03181d08, | ||
391 | 0x03191d07, 0x03191d07, 0x041a1c06, 0x041b1c05, | ||
392 | 0x051b1b05, 0x051c1b04, 0x061c1a04, 0x071d1903, | ||
393 | 0x071d1903, 0x081d1803, 0x081e1703, 0x091e1702, | ||
394 | 0x0a1f1601, 0x0a1f1502, 0x0b1f1501, 0x0c1f1401, | ||
395 | 0x0d201300, 0x0d201300, 0x0e201200, 0x0f201100, | ||
396 | |||
397 | 0x00102010, 0x0011200f, 0x00121f0f, 0x00131f0e, | ||
398 | 0x00141f0d, 0x01141f0c, 0x01141f0c, 0x01151e0c, | ||
399 | 0x02161e0a, 0x02171e09, 0x03171d09, 0x03181d08, | ||
400 | 0x03181d08, 0x04191c07, 0x041a1c06, 0x051a1b06, | ||
401 | 0x051b1b05, 0x061b1a05, 0x061c1a04, 0x071c1904, | ||
402 | 0x081c1903, 0x081d1803, 0x091d1703, 0x091e1702, | ||
403 | 0x0a1e1602, 0x0b1e1502, 0x0c1e1501, 0x0c1f1401, | ||
404 | 0x0d1f1400, 0x0e1f1300, 0x0e1f1201, 0x0f1f1200, | ||
405 | |||
406 | 0x00111e11, 0x00121e10, 0x00131e0f, 0x00131e0f, | ||
407 | 0x01131e0e, 0x01141d0e, 0x02151d0c, 0x02151d0c, | ||
408 | 0x02161d0b, 0x03161c0b, 0x03171c0a, 0x04171c09, | ||
409 | 0x04181b09, 0x05181b08, 0x05191b07, 0x06191a07, | ||
410 | 0x061a1a06, 0x071a1906, 0x071b1905, 0x081b1805, | ||
411 | 0x091b1804, 0x091c1704, 0x0a1c1703, 0x0a1c1604, | ||
412 | 0x0b1d1602, 0x0c1d1502, 0x0c1d1502, 0x0d1d1402, | ||
413 | 0x0e1d1401, 0x0e1e1301, 0x0f1e1300, 0x101e1200, | ||
414 | |||
415 | 0x00111e11, 0x00121e10, 0x00131d10, 0x01131d0f, | ||
416 | 0x01141d0e, 0x01141d0e, 0x02151c0d, 0x02151c0d, | ||
417 | 0x03161c0b, 0x03161c0b, 0x04171b0a, 0x04171b0a, | ||
418 | 0x05171b09, 0x05181a09, 0x06181a08, 0x06191a07, | ||
419 | 0x07191907, 0x071a1906, 0x081a1806, 0x081a1806, | ||
420 | 0x091a1805, 0x0a1b1704, 0x0a1b1704, 0x0b1c1603, | ||
421 | 0x0b1c1603, 0x0c1c1503, 0x0d1c1502, 0x0d1d1402, | ||
422 | 0x0e1d1401, 0x0f1d1301, 0x0f1d1301, 0x101e1200, | ||
423 | }; | ||
424 | |||
425 | static const u32 bicubic8coefftab32_left[480] = { | ||
426 | 0x40000000, 0x40ff0000, 0x3ffe0000, 0x3efe0000, | ||
427 | 0x3dfd0000, 0x3cfc0000, 0x3bfc0000, 0x39fc0000, | ||
428 | 0x36fc0000, 0x35fb0000, 0x33fb0000, 0x31fb0000, | ||
429 | 0x2ffb0000, 0x2cfb0000, 0x29fc0000, 0x27fc0000, | ||
430 | 0x24fc0000, 0x21fc0000, 0x1efd0000, 0x1cfd0000, | ||
431 | 0x19fd0000, 0x16fe0000, 0x14fe0000, 0x11fe0000, | ||
432 | 0x0dff0000, 0x0cff0000, 0x0aff0000, 0x08ff0000, | ||
433 | 0x05000000, 0x03000000, 0x02000000, 0x01000000, | ||
434 | |||
435 | 0x3904ff00, 0x3903ff00, 0x3902ff00, 0x38010000, | ||
436 | 0x37000000, 0x36ff0000, 0x35ff0000, 0x34fe0000, | ||
437 | 0x32fe0000, 0x31fd0000, 0x30fd0000, 0x2efc0000, | ||
438 | 0x2cfc0000, 0x2afc0000, 0x28fc0000, 0x26fc0000, | ||
439 | 0x24fc0000, 0x22fc0000, 0x20fc0000, 0x1efc0000, | ||
440 | 0x1cfc0000, 0x19fc0000, 0x17fc0000, 0x15fd0000, | ||
441 | 0x12fd0000, 0x11fd0000, 0x0ffd0000, 0x0dfe0000, | ||
442 | 0x0bfe0000, 0x09fe0000, 0x08fe0000, 0x06ff0000, | ||
443 | |||
444 | 0x3209fe00, 0x3407fe00, 0x3306fe00, 0x3305fe00, | ||
445 | 0x3204fe00, 0x3102ff00, 0x3102ff00, 0x3001ff00, | ||
446 | 0x2f00ff00, 0x2effff00, 0x2cff0000, 0x2bfe0000, | ||
447 | 0x29fe0000, 0x28fe0000, 0x26fd0000, 0x24fd0000, | ||
448 | 0x23fd0000, 0x21fd0000, 0x20fc0000, 0x1efc0000, | ||
449 | 0x1dfc0000, 0x1bfc0000, 0x19fc0000, 0x17fc0000, | ||
450 | 0x16fc0000, 0x14fc0000, 0x12fc0000, 0x10fd0000, | ||
451 | 0x0ffd0000, 0x0dfd0000, 0x0cfd0000, 0x0afd0000, | ||
452 | |||
453 | 0x2e0cfd00, 0x2e0bfd00, 0x2e09fd00, 0x2e08fd00, | ||
454 | 0x2e07fd00, 0x2c06fe00, 0x2c05fe00, 0x2b04fe00, | ||
455 | 0x2b03fe00, 0x2a02fe00, 0x2901fe00, 0x2701ff00, | ||
456 | 0x2700ff00, 0x26ffff00, 0x24ffff00, 0x23ffff00, | ||
457 | 0x22feff00, 0x20fe0000, 0x1ffe0000, 0x1efd0000, | ||
458 | 0x1dfd0000, 0x1bfd0000, 0x1afd0000, 0x19fd0000, | ||
459 | 0x17fd0000, 0x15fd0000, 0x13fd0000, 0x12fd0000, | ||
460 | 0x11fd0000, 0x10fd0000, 0x0ffd0000, 0x0cfd0000, | ||
461 | |||
462 | 0x2a0efd00, 0x2a0dfd00, 0x2a0cfd00, 0x290bfd00, | ||
463 | 0x290afd00, 0x2909fd00, 0x2908fd00, 0x2807fd00, | ||
464 | 0x2706fd00, 0x2705fd00, 0x2604fe00, 0x2603fe00, | ||
465 | 0x2502fe00, 0x2402fe00, 0x2401fe00, 0x2200fe00, | ||
466 | 0x2200fe00, 0x2000ff00, 0x1fffff00, 0x1effff00, | ||
467 | 0x1dfeff00, 0x1cfeff00, 0x1afeff00, 0x19feff00, | ||
468 | 0x17fe0000, 0x16fd0000, 0x15fd0000, 0x14fd0000, | ||
469 | 0x12fd0000, 0x11fd0000, 0x10fd0000, 0x0ffd0000, | ||
470 | |||
471 | 0x2610fd00, 0x260ffd00, 0x260efd00, 0x260dfd00, | ||
472 | 0x260cfd00, 0x260bfd00, 0x260afd00, 0x2609fd00, | ||
473 | 0x2508fd00, 0x2507fd00, 0x2406fd00, 0x2406fd00, | ||
474 | 0x2305fd00, 0x2304fd00, 0x2203fe00, 0x2103fe00, | ||
475 | 0x2002fe00, 0x1f01fe00, 0x1e01fe00, 0x1e00fe00, | ||
476 | 0x1c00fe00, 0x1b00fe00, 0x1afffe00, 0x19ffff00, | ||
477 | 0x18ffff00, 0x17feff00, 0x16feff00, 0x15feff00, | ||
478 | 0x14feff00, 0x13feff00, 0x11feff00, 0x10fd0000, | ||
479 | |||
480 | 0x2411feff, 0x2410feff, 0x240ffeff, 0x230efeff, | ||
481 | 0x240dfeff, 0x240cfeff, 0x230cfd00, 0x230bfd00, | ||
482 | 0x230afd00, 0x2309fd00, 0x2208fd00, 0x2108fd00, | ||
483 | 0x2007fd00, 0x2106fd00, 0x2005fd00, 0x1f05fd00, | ||
484 | 0x1f04fd00, 0x1e03fd00, 0x1d03fe00, 0x1c02fe00, | ||
485 | 0x1b02fe00, 0x1a01fe00, 0x1a01fe00, 0x1900fe00, | ||
486 | 0x1800fe00, 0x1700fe00, 0x16fffe00, 0x15fffe00, | ||
487 | 0x13ffff00, 0x12ffff00, 0x12feff00, 0x11feff00, | ||
488 | |||
489 | 0x2212fffe, 0x2211fffe, 0x2210ffff, 0x220ffeff, | ||
490 | 0x220efeff, 0x210efeff, 0x210dfeff, 0x210cfeff, | ||
491 | 0x210bfeff, 0x200bfeff, 0x200afeff, 0x1f09feff, | ||
492 | 0x1f08feff, 0x1d08fe00, 0x1e07fd00, 0x1e06fd00, | ||
493 | 0x1d06fd00, 0x1c05fd00, 0x1b04fe00, 0x1a04fe00, | ||
494 | 0x1a03fe00, 0x1903fe00, 0x1802fe00, 0x1802fe00, | ||
495 | 0x1701fe00, 0x1601fe00, 0x1501fe00, 0x1500fe00, | ||
496 | 0x1400fe00, 0x1400fe00, 0x13fffe00, 0x12fffe00, | ||
497 | |||
498 | 0x201200fe, 0x201100fe, 0x1f1100fe, 0x2010fffe, | ||
499 | 0x200ffffe, 0x1f0ffffe, 0x1f0efffe, 0x1e0dffff, | ||
500 | 0x1f0cfeff, 0x1e0cfeff, 0x1e0bfeff, 0x1e0afeff, | ||
501 | 0x1d0afeff, 0x1d09feff, 0x1c08feff, 0x1b08feff, | ||
502 | 0x1b07feff, 0x1a07feff, 0x1a06feff, 0x1a05feff, | ||
503 | 0x1805fe00, 0x1904fe00, 0x1704fe00, 0x1703fe00, | ||
504 | 0x1603fe00, 0x1602fe00, 0x1402fe00, 0x1402fe00, | ||
505 | 0x1401fe00, 0x1301fe00, 0x1201fe00, 0x1200fe00, | ||
506 | |||
507 | 0x1c1202fe, 0x1c1102fe, 0x1b1102fe, 0x1c1001fe, | ||
508 | 0x1b1001fe, 0x1c0f01fe, 0x1b0f00fe, 0x1b0e00fe, | ||
509 | 0x1b0e00fe, 0x1b0d00fe, 0x1b0c00fe, 0x1a0cfffe, | ||
510 | 0x1a0bfffe, 0x1a0bfffe, 0x190afffe, 0x190afffe, | ||
511 | 0x1909fffe, 0x1709ffff, 0x1808ffff, 0x1708feff, | ||
512 | 0x1707feff, 0x1707feff, 0x1606feff, 0x1506feff, | ||
513 | 0x1505feff, 0x1505feff, 0x1404feff, 0x1404feff, | ||
514 | 0x1404feff, 0x1303feff, 0x1203feff, 0x1202feff, | ||
515 | |||
516 | 0x191104fe, 0x191104fe, 0x191003fe, 0x191003fe, | ||
517 | 0x171003fe, 0x180f03fe, 0x180f02fe, 0x180e02fe, | ||
518 | 0x180e02fe, 0x180d01fe, 0x180d01fe, 0x180d01fe, | ||
519 | 0x170c01fe, 0x160c01fe, 0x170b00fe, 0x170b00fe, | ||
520 | 0x160a00fe, 0x160a00fe, 0x160a00fe, 0x150900fe, | ||
521 | 0x1509fffe, 0x1508fffe, 0x1508fffe, 0x1408fffe, | ||
522 | 0x1407fffe, 0x1307ffff, 0x1306ffff, 0x1206ffff, | ||
523 | 0x1206ffff, 0x1205ffff, 0x1205ffff, 0x1104feff, | ||
524 | |||
525 | 0x161006ff, 0x161005ff, 0x161005ff, 0x160f05ff, | ||
526 | 0x160f04ff, 0x150f04ff, 0x150e04ff, 0x150e04ff, | ||
527 | 0x150e03ff, 0x150d03ff, 0x150d03ff, 0x150d02ff, | ||
528 | 0x140c02ff, 0x150c02fe, 0x150c02fe, 0x150b02fe, | ||
529 | 0x140b01fe, 0x140b01fe, 0x140a01fe, 0x140a01fe, | ||
530 | 0x140a01fe, 0x130900fe, 0x130900fe, 0x130900fe, | ||
531 | 0x130800fe, 0x120800fe, 0x120800fe, 0x120700fe, | ||
532 | 0x120700fe, 0x1107fffe, 0x1106fffe, 0x1106fffe, | ||
533 | |||
534 | 0x140f0700, 0x140f0600, 0x140f0600, 0x140f0600, | ||
535 | 0x140e0600, 0x130e0500, 0x140e05ff, 0x130e05ff, | ||
536 | 0x140d05ff, 0x130d04ff, 0x130d04ff, 0x120d04ff, | ||
537 | 0x130c04ff, 0x130c03ff, 0x130c03ff, 0x120c03ff, | ||
538 | 0x120b03ff, 0x120b02ff, 0x120b02ff, 0x120a02ff, | ||
539 | 0x120a02ff, 0x110a02ff, 0x110a01ff, 0x120901ff, | ||
540 | 0x100901ff, 0x100901ff, 0x110801ff, 0x110801ff, | ||
541 | 0x100800ff, 0x100800ff, 0x100700ff, 0x100700fe, | ||
542 | |||
543 | 0x120f0701, 0x120e0701, 0x120e0701, 0x120e0701, | ||
544 | 0x120e0600, 0x110e0600, 0x120d0600, 0x120d0600, | ||
545 | 0x120d0500, 0x120d0500, 0x110d0500, 0x110c0500, | ||
546 | 0x110c0500, 0x110c0400, 0x110c0400, 0x110b04ff, | ||
547 | 0x110b04ff, 0x110b04ff, 0x110b03ff, 0x110b03ff, | ||
548 | 0x110a03ff, 0x110a03ff, 0x100a03ff, 0x110a02ff, | ||
549 | 0x100902ff, 0x100902ff, 0x100902ff, 0x0f0902ff, | ||
550 | 0x0e0902ff, 0x100801ff, 0x0f0801ff, 0x0f0801ff, | ||
551 | |||
552 | 0x100e0802, 0x100e0802, 0x110e0702, 0x110d0701, | ||
553 | 0x110d0701, 0x100d0701, 0x100d0701, 0x110d0601, | ||
554 | 0x110d0601, 0x110c0601, 0x110c0601, 0x100c0600, | ||
555 | 0x100c0500, 0x100c0500, 0x100c0500, 0x100b0500, | ||
556 | 0x100b0500, 0x100b0400, 0x100b0400, 0x0f0b0400, | ||
557 | 0x100a0400, 0x0f0a0400, 0x0f0a0400, 0x0f0a0300, | ||
558 | 0x0f0a03ff, 0x0f0903ff, 0x0f0903ff, 0x0f0903ff, | ||
559 | 0x0f0903ff, 0x0f0902ff, 0x0f0902ff, 0x0f0802ff | ||
560 | }; | ||
561 | |||
562 | static const u32 bicubic8coefftab32_right[480] = { | ||
563 | 0x00000000, 0x00000001, 0x00000003, 0x00000004, | ||
564 | 0x00000006, 0x0000ff09, 0x0000ff0a, 0x0000ff0c, | ||
565 | 0x0000ff0f, 0x0000fe12, 0x0000fe14, 0x0000fe16, | ||
566 | 0x0000fd19, 0x0000fd1c, 0x0000fd1e, 0x0000fc21, | ||
567 | 0x0000fc24, 0x0000fc27, 0x0000fc29, 0x0000fb2c, | ||
568 | 0x0000fb2f, 0x0000fb31, 0x0000fb33, 0x0000fb36, | ||
569 | 0x0000fc38, 0x0000fc39, 0x0000fc3b, 0x0000fc3d, | ||
570 | 0x0000fd3e, 0x0000fe3f, 0x0000fe40, 0x0000ff40, | ||
571 | |||
572 | 0x0000ff05, 0x0000ff06, 0x0000fe08, 0x0000fe09, | ||
573 | 0x0000fe0b, 0x0000fe0d, 0x0000fd0f, 0x0000fd11, | ||
574 | 0x0000fd13, 0x0000fd15, 0x0000fc17, 0x0000fc1a, | ||
575 | 0x0000fc1c, 0x0000fc1e, 0x0000fc20, 0x0000fc22, | ||
576 | 0x0000fc24, 0x0000fc26, 0x0000fc28, 0x0000fc2a, | ||
577 | 0x0000fc2c, 0x0000fc2f, 0x0000fd30, 0x0000fd31, | ||
578 | 0x0000fe33, 0x0000fe34, 0x0000ff35, 0x0000ff36, | ||
579 | 0x00000037, 0x00000138, 0x00ff0239, 0x00ff0339, | ||
580 | |||
581 | 0x0000fe09, 0x0000fd0a, 0x0000fd0c, 0x0000fd0d, | ||
582 | 0x0000fd0f, 0x0000fd11, 0x0000fc12, 0x0000fc14, | ||
583 | 0x0000fc16, 0x0000fc18, 0x0000fc19, 0x0000fc1b, | ||
584 | 0x0000fc1d, 0x0000fc1e, 0x0000fc21, 0x0000fd22, | ||
585 | 0x0000fd23, 0x0000fd25, 0x0000fd27, 0x0000fe28, | ||
586 | 0x0000fe29, 0x0000fe2b, 0x0000ff2c, 0x00ffff2f, | ||
587 | 0x00ff002f, 0x00ff0130, 0x00ff0231, 0x00ff0232, | ||
588 | 0x00fe0432, 0x00fe0533, 0x00fe0633, 0x00fe0734, | ||
589 | |||
590 | 0x0000fd0c, 0x0000fd0d, 0x0000fd0f, 0x0000fd10, | ||
591 | 0x0000fd11, 0x0000fd13, 0x0000fd14, 0x0000fd16, | ||
592 | 0x0000fd17, 0x0000fd19, 0x0000fd1b, 0x0000fd1c, | ||
593 | 0x0000fd1d, 0x0000fd1f, 0x0000fe20, 0x0000fe21, | ||
594 | 0x00fffe24, 0x00ffff24, 0x00ffff25, 0x00ffff27, | ||
595 | 0x00ff0027, 0x00ff0128, 0x00fe012a, 0x00fe022a, | ||
596 | 0x00fe032b, 0x00fe042c, 0x00fe052d, 0x00fe062d, | ||
597 | 0x00fd072e, 0x00fd082e, 0x00fd092e, 0x00fd0b2f, | ||
598 | |||
599 | 0x0000fd0e, 0x0000fd0f, 0x0000fd10, 0x0000fd12, | ||
600 | 0x0000fd13, 0x0000fd14, 0x0000fd15, 0x0000fd17, | ||
601 | 0x0000fe18, 0x00fffe1a, 0x00fffe1b, 0x00fffe1c, | ||
602 | 0x00fffe1e, 0x00ffff1e, 0x00ffff1f, 0x00ff0021, | ||
603 | 0x00fe0022, 0x00fe0023, 0x00fe0124, 0x00fe0224, | ||
604 | 0x00fe0226, 0x00fe0326, 0x00fe0427, 0x00fd0528, | ||
605 | 0x00fd0628, 0x00fd0729, 0x00fd0829, 0x00fd0929, | ||
606 | 0x00fd0a2a, 0x00fd0b2a, 0x00fd0c2a, 0x00fd0d2a, | ||
607 | |||
608 | 0x0000fd10, 0x0000fd11, 0x00fffe12, 0x00fffe13, | ||
609 | 0x00fffe14, 0x00fffe15, 0x00fffe16, 0x00fffe17, | ||
610 | 0x00ffff18, 0x00ffff19, 0x00feff1c, 0x00fe001b, | ||
611 | 0x00fe001d, 0x00fe001e, 0x00fe011e, 0x00fe011f, | ||
612 | 0x00fe0220, 0x00fe0321, 0x00fe0322, 0x00fd0423, | ||
613 | 0x00fd0524, 0x00fd0624, 0x00fd0626, 0x00fd0725, | ||
614 | 0x00fd0825, 0x00fd0926, 0x00fd0a26, 0x00fd0b26, | ||
615 | 0x00fd0c26, 0x00fd0d26, 0x00fd0e27, 0x00fd0f27, | ||
616 | |||
617 | 0x00fffe11, 0x00fffe12, 0x00fffe13, 0x00ffff14, | ||
618 | 0x00ffff14, 0x00feff16, 0x00feff17, 0x00fe0017, | ||
619 | 0x00fe0018, 0x00fe0019, 0x00fe011a, 0x00fe011b, | ||
620 | 0x00fe021c, 0x00fe021c, 0x00fe031d, 0x00fd031f, | ||
621 | 0x00fd041f, 0x00fd0520, 0x00fd0520, 0x00fd0621, | ||
622 | 0x00fd0721, 0x00fd0822, 0x00fd0822, 0x00fd0923, | ||
623 | 0x00fd0a23, 0x00fd0b23, 0x00fd0b25, 0x00fe0c24, | ||
624 | 0x00fe0d24, 0x00fe0e24, 0x00fe0f24, 0x00fe1024, | ||
625 | |||
626 | 0x00feff12, 0x00feff13, 0x00feff13, 0x00fe0014, | ||
627 | 0x00fe0015, 0x00fe0016, 0x00fe0116, 0x00fe0117, | ||
628 | 0x00fe0118, 0x00fe0218, 0x00fe0219, 0x00fe031a, | ||
629 | 0x00fe031b, 0x00fe041b, 0x00fd041d, 0x00fd051d, | ||
630 | 0x00fd061d, 0x00fd061f, 0x00fe071e, 0x00fe081e, | ||
631 | 0x00fe081f, 0x00fe091f, 0x00fe0a20, 0x00fe0a20, | ||
632 | 0x00fe0b21, 0x00fe0c21, 0x00fe0d21, 0x00fe0d22, | ||
633 | 0x00fe0e22, 0x00fe0f21, 0x00ff1021, 0x00ff1022, | ||
634 | |||
635 | 0x00fe0012, 0x00fe0013, 0x00fe0113, 0x00fe0114, | ||
636 | 0x00fe0115, 0x00fe0215, 0x00fe0216, 0x00fe0217, | ||
637 | 0x00fe0317, 0x00fe0318, 0x00fe0418, 0x00fe0419, | ||
638 | 0x00fe0519, 0x00fe051a, 0x00fe061b, 0x00fe071b, | ||
639 | 0x00fe071c, 0x00fe081c, 0x00fe081d, 0x00fe091d, | ||
640 | 0x00fe0a1d, 0x00fe0a1d, 0x00fe0b1e, 0x00fe0c1e, | ||
641 | 0x00ff0c1e, 0x00ff0d1e, 0x00ff0e1f, 0x00ff0e1f, | ||
642 | 0x00ff0f1f, 0x00ff0f20, 0x0000101f, 0x0000111f, | ||
643 | |||
644 | 0x00fe0212, 0x00fe0312, 0x00fe0313, 0x00fe0314, | ||
645 | 0x00fe0414, 0x00fe0414, 0x00fe0515, 0x00fe0516, | ||
646 | 0x00fe0516, 0x00fe0616, 0x00fe0617, 0x00fe0718, | ||
647 | 0x00fe0719, 0x00fe0818, 0x00ff0819, 0x00ff0918, | ||
648 | 0x00ff0919, 0x00ff0a19, 0x00ff0a19, 0x00ff0b1a, | ||
649 | 0x00ff0b1b, 0x00ff0c1a, 0x00000c1b, 0x00000d1b, | ||
650 | 0x00000d1c, 0x00000e1b, 0x00000e1d, 0x00010f1b, | ||
651 | 0x00010f1b, 0x0001101c, 0x0001101d, 0x0002111c, | ||
652 | |||
653 | 0x00fe0412, 0x00fe0412, 0x00ff0512, 0x00ff0512, | ||
654 | 0x00ff0613, 0x00ff0613, 0x00ff0614, 0x00ff0714, | ||
655 | 0x00ff0714, 0x00ff0815, 0x00ff0815, 0x00ff0815, | ||
656 | 0x00ff0916, 0x00000916, 0x00000a16, 0x00000a16, | ||
657 | 0x00000a18, 0x00000b17, 0x00000b17, 0x00010c17, | ||
658 | 0x00010c18, 0x00010d18, 0x00010d18, 0x00010d19, | ||
659 | 0x00020e18, 0x00020e18, 0x00020f18, 0x00030f18, | ||
660 | 0x00030f18, 0x00031018, 0x00031018, 0x00041119, | ||
661 | |||
662 | 0x00ff0610, 0x00ff0611, 0x00ff0611, 0x00ff0711, | ||
663 | 0x00000711, 0x00000712, 0x00000812, 0x00000812, | ||
664 | 0x00000813, 0x00000913, 0x00000913, 0x00000914, | ||
665 | 0x00010a14, 0x00010a14, 0x00010a14, 0x00010b14, | ||
666 | 0x00010b16, 0x00020b15, 0x00020c15, 0x00020c15, | ||
667 | 0x00020c15, 0x00020d17, 0x00030d16, 0x00030d16, | ||
668 | 0x00030e16, 0x00040e16, 0x00040e16, 0x00040f16, | ||
669 | 0x00040f16, 0x00050f17, 0x00051017, 0x00051017, | ||
670 | |||
671 | 0x0000070f, 0x00000710, 0x00000710, 0x00000710, | ||
672 | 0x00000810, 0x00010811, 0x00010811, 0x00010911, | ||
673 | 0x00010911, 0x00010913, 0x00010913, 0x00020a12, | ||
674 | 0x00020a12, 0x00020a13, 0x00020b12, 0x00020b13, | ||
675 | 0x00030b13, 0x00030c13, 0x00030c13, 0x00030c14, | ||
676 | 0x00040c13, 0x00040d13, 0x00040d14, 0x00040d14, | ||
677 | 0x00050e14, 0x00050e14, 0x00050e14, 0x00050e14, | ||
678 | 0x00060f14, 0x00060f14, 0x00060f15, 0x00061015, | ||
679 | |||
680 | 0x0001070f, 0x0001080f, 0x0001080f, 0x0001080f, | ||
681 | 0x00010811, 0x00020910, 0x00020910, 0x00020910, | ||
682 | 0x00020911, 0x00020a10, 0x00030a10, 0x00030a11, | ||
683 | 0x00030a11, 0x00030b11, 0x00030b11, 0x00040b12, | ||
684 | 0x00040b12, 0x00040c11, 0x00040c12, 0x00040c12, | ||
685 | 0x00050c12, 0x00050c12, 0x00050d12, 0x00050d12, | ||
686 | 0x00060d13, 0x00060d13, 0x00060e12, 0x00060e13, | ||
687 | 0x00070e13, 0x00070e13, 0x00070f13, 0x00070f13, | ||
688 | |||
689 | 0x0002080e, 0x0002080e, 0x0002080e, 0x00020810, | ||
690 | 0x0002090f, 0x0003090f, 0x0003090f, 0x0003090f, | ||
691 | 0x0003090f, 0x00030a0f, 0x00030a0f, 0x00040a10, | ||
692 | 0x00040a11, 0x00040b10, 0x00040b10, 0x00040b11, | ||
693 | 0x00050b10, 0x00050b11, 0x00050c10, 0x00050c11, | ||
694 | 0x00050c11, 0x00060c11, 0x00060c11, 0x00060d11, | ||
695 | 0x00060d12, 0x00070d12, 0x00070d12, 0x00070e11, | ||
696 | 0x00070e11, 0x00070e12, 0x00080e11, 0x00080e12 | ||
697 | }; | ||
698 | |||
699 | static const u32 bicubic4coefftab32[480] = { | ||
700 | 0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd, | ||
701 | 0x00063dfd, 0xff083dfc, 0xff0a3bfc, 0xff0c39fc, | ||
702 | 0xff0e37fc, 0xfe1136fb, 0xfe1433fb, 0xfe1631fb, | ||
703 | 0xfd192ffb, 0xfd1c2cfb, 0xfd1e29fc, 0xfc2127fc, | ||
704 | 0xfc2424fc, 0xfc2721fc, 0xfc291efd, 0xfb2c1cfd, | ||
705 | 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfb3611fe, | ||
706 | 0xfc370eff, 0xfc390cff, 0xfc3b0aff, 0xfc3d08ff, | ||
707 | 0xfd3d0600, 0xfd3f0400, 0xfe3f0300, 0xff400100, | ||
708 | |||
709 | 0xfe053904, 0xfe063903, 0xfe083901, 0xfe0a3800, | ||
710 | 0xfd0b3800, 0xfe0d36ff, 0xfd0f35ff, 0xfd1134fe, | ||
711 | 0xfd1332fe, 0xfd1531fd, 0xfc1730fd, 0xfc1a2efc, | ||
712 | 0xfc1c2cfc, 0xfc1e2afc, 0xfc2028fc, 0xfc2226fc, | ||
713 | 0xfc2424fc, 0xfc2622fc, 0xfc2820fc, 0xfc2a1efc, | ||
714 | 0xfc2c1cfc, 0xfc2e1afc, 0xfd3017fc, 0xfd3115fd, | ||
715 | 0xfe3213fd, 0xfe3411fd, 0xff350ffd, 0xff360dfe, | ||
716 | 0x00370bfe, 0x013809fe, 0x023808fe, 0x033806ff, | ||
717 | |||
718 | 0xfd093208, 0xfd0a3207, 0xfd0c3205, 0xfd0d3204, | ||
719 | 0xfc0f3203, 0xfc113102, 0xfc123002, 0xfc143000, | ||
720 | 0xfc152f00, 0xfc172d00, 0xfc192cff, 0xfc1b2bfe, | ||
721 | 0xfc1d29fe, 0xfc1e28fe, 0xfc2027fd, 0xfd2125fd, | ||
722 | 0xfd2323fd, 0xfd2521fd, 0xfd2720fc, 0xfe281efc, | ||
723 | 0xfe291dfc, 0xfe2b1bfc, 0xff2c19fc, 0x002d17fc, | ||
724 | 0x002e16fc, 0x012f14fc, 0x022f12fd, 0x023110fd, | ||
725 | 0x03310ffd, 0x05310dfd, 0x06320bfd, 0x07320afd, | ||
726 | |||
727 | 0xfc0c2d0b, 0xfc0d2d0a, 0xfc0e2d09, 0xfc102d07, | ||
728 | 0xfc112c07, 0xfc132c05, 0xfc142c04, 0xfc162b03, | ||
729 | 0xfc172a03, 0xfc192a01, 0xfc1a2901, 0xfd1b2800, | ||
730 | 0xfd1c2700, 0xfd1e2500, 0xfe1f24ff, 0xfe2023ff, | ||
731 | 0xfe2222fe, 0xff2320fe, 0xff241ffe, 0x00251efd, | ||
732 | 0x00271cfd, 0x01271bfd, 0x01281afd, 0x022918fd, | ||
733 | 0x032a16fd, 0x032b15fd, 0x042b14fd, 0x052c12fd, | ||
734 | 0x072c10fd, 0x082c0ffd, 0x092c0efd, 0x0a2c0dfd, | ||
735 | |||
736 | 0xfd0d290d, 0xfd0e290c, 0xfd0f290b, 0xfd11280a, | ||
737 | 0xfd122809, 0xfd132808, 0xfd142807, 0xfd162706, | ||
738 | 0xfd172705, 0xfd192604, 0xfe1a2503, 0xfe1b2502, | ||
739 | 0xfe1c2402, 0xfe1d2302, 0xff1e2201, 0xff1f2101, | ||
740 | 0x00202000, 0x00211f00, 0x01221eff, 0x02221dff, | ||
741 | 0x02241cfe, 0x03241bfe, 0x042519fe, 0x042618fe, | ||
742 | 0x052617fe, 0x062716fd, 0x072714fe, 0x082713fe, | ||
743 | 0x092812fd, 0x0a2811fd, 0x0b2810fd, 0x0c280ffd, | ||
744 | |||
745 | 0xfd0f250f, 0xfd10250e, 0xfd11250d, 0xfd12250c, | ||
746 | 0xfd13250b, 0xfe13250a, 0xfe152409, 0xfe162408, | ||
747 | 0xfe172308, 0xff182306, 0xff192305, 0xff1a2205, | ||
748 | 0x001b2104, 0x001c2103, 0x001d2003, 0x011e1f02, | ||
749 | 0x011f1f01, 0x021f1e01, 0x03201d00, 0x03211c00, | ||
750 | 0x04211b00, 0x05221aff, 0x062219ff, 0x062318ff, | ||
751 | 0x082316ff, 0x082316ff, 0x092415fe, 0x0a2414fe, | ||
752 | 0x0b2413fe, 0x0c2412fe, 0x0d2411fe, 0x0e2410fe, | ||
753 | |||
754 | 0xfe10230f, 0xfe11230e, 0xfe12220e, 0xfe13220d, | ||
755 | 0xfe14220c, 0xff14220b, 0xff15220a, 0xff16210a, | ||
756 | 0x00162109, 0x00172108, 0x00182008, 0x01192006, | ||
757 | 0x011a1f06, 0x021a1f05, 0x021b1e05, 0x031c1d04, | ||
758 | 0x031d1d03, 0x041d1c03, 0x041e1b03, 0x051e1b02, | ||
759 | 0x061f1a01, 0x06201901, 0x07201801, 0x08201800, | ||
760 | 0x09201700, 0x0a211500, 0x0b2115ff, 0x0c2114ff, | ||
761 | 0x0c2213ff, 0x0d2212ff, 0x0e2211ff, 0x0f2211fe, | ||
762 | |||
763 | 0xff112010, 0xff12200f, 0xff12200f, 0xff13200e, | ||
764 | 0x0013200d, 0x0014200c, 0x00151f0c, 0x00161f0b, | ||
765 | 0x01161f0a, 0x01171e0a, 0x02171e09, 0x02181e08, | ||
766 | 0x03191d07, 0x03191d07, 0x041a1c06, 0x041b1c05, | ||
767 | 0x051b1b05, 0x051c1b04, 0x061c1a04, 0x071c1a03, | ||
768 | 0x071d1903, 0x081e1802, 0x091d1802, 0x091e1702, | ||
769 | 0x0a1f1601, 0x0b1f1600, 0x0b1f1501, 0x0c201400, | ||
770 | 0x0d1f1400, 0x0e2013ff, 0x0f1f1200, 0x102011ff, | ||
771 | |||
772 | 0x00111f10, 0x00121e10, 0x00131e0f, 0x00131e0f, | ||
773 | 0x01131e0e, 0x01141e0d, 0x01151d0d, 0x02151d0c, | ||
774 | 0x02161d0b, 0x03161d0a, 0x03171c0a, 0x04171c09, | ||
775 | 0x04181c08, 0x05181b08, 0x05191b07, 0x06191a07, | ||
776 | 0x061a1a06, 0x071a1906, 0x071b1905, 0x081b1805, | ||
777 | 0x081c1804, 0x091c1704, 0x0a1c1703, 0x0a1d1603, | ||
778 | 0x0b1d1602, 0x0c1d1502, 0x0c1d1502, 0x0d1e1401, | ||
779 | 0x0e1d1401, 0x0e1e1301, 0x0f1e1300, 0x101e1200, | ||
780 | |||
781 | 0x02111c11, 0x02121c10, 0x02131b10, 0x03131b0f, | ||
782 | 0x03131b0f, 0x03141b0e, 0x04141b0d, 0x04151a0d, | ||
783 | 0x05151a0c, 0x05151a0c, 0x05161a0b, 0x0616190b, | ||
784 | 0x0616190b, 0x0716190a, 0x0717180a, 0x08171809, | ||
785 | 0x08181808, 0x09181708, 0x09181708, 0x0a181707, | ||
786 | 0x0a191607, 0x0b191606, 0x0b1a1605, 0x0c1a1505, | ||
787 | 0x0c1a1505, 0x0d1a1504, 0x0d1b1404, 0x0e1b1403, | ||
788 | 0x0f1b1303, 0x0f1b1303, 0x101b1302, 0x101c1202, | ||
789 | |||
790 | 0x04111a11, 0x04121911, 0x04131910, 0x0513190f, | ||
791 | 0x0513190f, 0x0513190f, 0x0613190e, 0x0614180e, | ||
792 | 0x0714180d, 0x0714180d, 0x0715180c, 0x0814180c, | ||
793 | 0x0815170c, 0x0816170b, 0x0916170a, 0x0916170a, | ||
794 | 0x0a16160a, 0x0a171609, 0x0a171609, 0x0b171608, | ||
795 | 0x0b171509, 0x0c171508, 0x0c181507, 0x0d171507, | ||
796 | 0x0d181407, 0x0e181406, 0x0e181406, 0x0e191306, | ||
797 | 0x0f191305, 0x0f191305, 0x10191304, 0x10191205, | ||
798 | |||
799 | 0x05121811, 0x06121810, 0x06121810, 0x06131710, | ||
800 | 0x0713170f, 0x0713170f, 0x0713170f, 0x0813170e, | ||
801 | 0x0813170e, 0x0814170d, 0x0914160d, 0x0914160d, | ||
802 | 0x0914160d, 0x0a14160c, 0x0a15160b, 0x0a15150c, | ||
803 | 0x0b15150b, 0x0b15150b, 0x0b16150a, 0x0c15150a, | ||
804 | 0x0c16140a, 0x0d161409, 0x0d161409, 0x0d171408, | ||
805 | 0x0e161408, 0x0e171308, 0x0e171308, 0x0f171307, | ||
806 | 0x0f171307, 0x10171306, 0x10181206, 0x10181206, | ||
807 | |||
808 | 0x07111711, 0x07121710, 0x07121611, 0x08121610, | ||
809 | 0x08121610, 0x0813160f, 0x0912160f, 0x0913160e, | ||
810 | 0x0913160e, 0x0913160e, 0x0a14150d, 0x0a14150d, | ||
811 | 0x0a14150d, 0x0b14150c, 0x0b14150c, 0x0b14150c, | ||
812 | 0x0c14140c, 0x0c15140b, 0x0c15140b, 0x0c15140b, | ||
813 | 0x0d15140a, 0x0d15140a, 0x0d15140a, 0x0e161309, | ||
814 | 0x0e161309, 0x0e161309, 0x0f151309, 0x0f161308, | ||
815 | 0x0f161209, 0x10161208, 0x10161208, 0x10171207, | ||
816 | |||
817 | 0x0a111411, 0x0b111410, 0x0b111410, 0x0b111410, | ||
818 | 0x0b111410, 0x0b12140f, 0x0b12140f, 0x0c12130f, | ||
819 | 0x0c12130f, 0x0c12130f, 0x0c12130f, 0x0c12130f, | ||
820 | 0x0d12130e, 0x0d12130e, 0x0d12130e, 0x0d13130d, | ||
821 | 0x0d13130d, 0x0d13130d, 0x0e12130d, 0x0e13120d, | ||
822 | 0x0e13120d, 0x0e13120d, 0x0e13120d, 0x0f13120c, | ||
823 | 0x0f13120c, 0x0f13120c, 0x0f14120b, 0x0f14120b, | ||
824 | 0x1013120b, 0x1013120b, 0x1013120b, 0x1014110b, | ||
825 | |||
826 | 0x0c111310, 0x0c111310, 0x0c111310, 0x0d101310, | ||
827 | 0x0d101310, 0x0d111210, 0x0d111210, 0x0d111210, | ||
828 | 0x0d12120f, 0x0d12120f, 0x0d12120f, 0x0d12120f, | ||
829 | 0x0e11120f, 0x0e12120e, 0x0e12120e, 0x0e12120e, | ||
830 | 0x0e12120e, 0x0e12120e, 0x0e12120e, 0x0e12120e, | ||
831 | 0x0f11120e, 0x0f12120d, 0x0f12120d, 0x0f12120d, | ||
832 | 0x0f12120d, 0x0f12110e, 0x0f12110e, 0x0f12110e, | ||
833 | 0x1012110d, 0x1012110d, 0x1013110c, 0x1013110c, | ||
834 | }; | ||
835 | |||
836 | static int sun8i_vi_scaler_coef_index(unsigned int step) | ||
837 | { | ||
838 | unsigned int scale, int_part, float_part; | ||
839 | |||
840 | scale = step >> (SUN8I_VI_SCALER_SCALE_FRAC - 3); | ||
841 | int_part = scale >> 3; | ||
842 | float_part = scale & 0x7; | ||
843 | |||
844 | switch (int_part) { | ||
845 | case 0: | ||
846 | return 0; | ||
847 | case 1: | ||
848 | return float_part; | ||
849 | case 2: | ||
850 | return 8 + (float_part >> 1); | ||
851 | case 3: | ||
852 | return 12; | ||
853 | case 4: | ||
854 | return 13; | ||
855 | default: | ||
856 | return 14; | ||
857 | } | ||
858 | } | ||
859 | |||
860 | static void sun8i_vi_scaler_set_coeff(struct regmap *map, int layer, | ||
861 | u32 hstep, u32 vstep, | ||
862 | const struct drm_format_info *format) | ||
863 | { | ||
864 | const u32 *ch_left, *ch_right, *cy; | ||
865 | int offset, i; | ||
866 | |||
867 | if (format->hsub == 1 && format->vsub == 1) { | ||
868 | ch_left = lan3coefftab32_left; | ||
869 | ch_right = lan3coefftab32_right; | ||
870 | cy = lan2coefftab32; | ||
871 | } else { | ||
872 | ch_left = bicubic8coefftab32_left; | ||
873 | ch_right = bicubic8coefftab32_right; | ||
874 | cy = bicubic4coefftab32; | ||
875 | } | ||
876 | |||
877 | offset = sun8i_vi_scaler_coef_index(hstep) * | ||
878 | SUN8I_VI_SCALER_COEFF_COUNT; | ||
879 | for (i = 0; i < SUN8I_VI_SCALER_COEFF_COUNT; i++) { | ||
880 | regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF0(layer, i), | ||
881 | lan3coefftab32_left[offset + i]); | ||
882 | regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF1(layer, i), | ||
883 | lan3coefftab32_right[offset + i]); | ||
884 | regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF0(layer, i), | ||
885 | ch_left[offset + i]); | ||
886 | regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF1(layer, i), | ||
887 | ch_right[offset + i]); | ||
888 | } | ||
889 | |||
890 | offset = sun8i_vi_scaler_coef_index(hstep) * | ||
891 | SUN8I_VI_SCALER_COEFF_COUNT; | ||
892 | for (i = 0; i < SUN8I_VI_SCALER_COEFF_COUNT; i++) { | ||
893 | regmap_write(map, SUN8I_SCALER_VSU_YVCOEFF(layer, i), | ||
894 | lan2coefftab32[offset + i]); | ||
895 | regmap_write(map, SUN8I_SCALER_VSU_CVCOEFF(layer, i), | ||
896 | cy[offset + i]); | ||
897 | } | ||
898 | } | ||
899 | |||
900 | void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable) | ||
901 | { | ||
902 | u32 val; | ||
903 | |||
904 | if (enable) | ||
905 | val = SUN8I_SCALER_VSU_CTRL_EN | | ||
906 | SUN8I_SCALER_VSU_CTRL_COEFF_RDY; | ||
907 | else | ||
908 | val = 0; | ||
909 | |||
910 | regmap_write(mixer->engine.regs, SUN8I_SCALER_VSU_CTRL(layer), val); | ||
911 | } | ||
912 | |||
913 | void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer, | ||
914 | u32 src_w, u32 src_h, u32 dst_w, u32 dst_h, | ||
915 | u32 hscale, u32 vscale, u32 hphase, u32 vphase, | ||
916 | const struct drm_format_info *format) | ||
917 | { | ||
918 | u32 chphase, cvphase; | ||
919 | u32 insize, outsize; | ||
920 | |||
921 | hphase <<= SUN8I_VI_SCALER_PHASE_FRAC - 16; | ||
922 | vphase <<= SUN8I_VI_SCALER_PHASE_FRAC - 16; | ||
923 | hscale <<= SUN8I_VI_SCALER_SCALE_FRAC - 16; | ||
924 | vscale <<= SUN8I_VI_SCALER_SCALE_FRAC - 16; | ||
925 | |||
926 | insize = SUN8I_VI_SCALER_SIZE(src_w, src_h); | ||
927 | outsize = SUN8I_VI_SCALER_SIZE(dst_w, dst_h); | ||
928 | |||
929 | /* | ||
930 | * This is chroma V/H phase calculation as it appears in | ||
931 | * BSP driver. There is no detailed explanation. YUV 420 | ||
932 | * chroma is threated specialy for some reason. | ||
933 | */ | ||
934 | if (format->hsub == 2 && format->vsub == 2) { | ||
935 | chphase = hphase >> 1; | ||
936 | cvphase = (vphase >> 1) - | ||
937 | (1UL << (SUN8I_VI_SCALER_SCALE_FRAC - 2)); | ||
938 | } else { | ||
939 | chphase = hphase; | ||
940 | cvphase = vphase; | ||
941 | } | ||
942 | |||
943 | regmap_write(mixer->engine.regs, | ||
944 | SUN8I_SCALER_VSU_OUTSIZE(layer), outsize); | ||
945 | regmap_write(mixer->engine.regs, | ||
946 | SUN8I_SCALER_VSU_YINSIZE(layer), insize); | ||
947 | regmap_write(mixer->engine.regs, | ||
948 | SUN8I_SCALER_VSU_YHSTEP(layer), hscale); | ||
949 | regmap_write(mixer->engine.regs, | ||
950 | SUN8I_SCALER_VSU_YVSTEP(layer), vscale); | ||
951 | regmap_write(mixer->engine.regs, | ||
952 | SUN8I_SCALER_VSU_YHPHASE(layer), hphase); | ||
953 | regmap_write(mixer->engine.regs, | ||
954 | SUN8I_SCALER_VSU_YVPHASE(layer), vphase); | ||
955 | regmap_write(mixer->engine.regs, | ||
956 | SUN8I_SCALER_VSU_CINSIZE(layer), | ||
957 | SUN8I_VI_SCALER_SIZE(src_w / format->hsub, | ||
958 | src_h / format->vsub)); | ||
959 | regmap_write(mixer->engine.regs, | ||
960 | SUN8I_SCALER_VSU_CHSTEP(layer), | ||
961 | hscale / format->hsub); | ||
962 | regmap_write(mixer->engine.regs, | ||
963 | SUN8I_SCALER_VSU_CVSTEP(layer), | ||
964 | vscale / format->vsub); | ||
965 | regmap_write(mixer->engine.regs, | ||
966 | SUN8I_SCALER_VSU_CHPHASE(layer), chphase); | ||
967 | regmap_write(mixer->engine.regs, | ||
968 | SUN8I_SCALER_VSU_CVPHASE(layer), cvphase); | ||
969 | sun8i_vi_scaler_set_coeff(mixer->engine.regs, layer, | ||
970 | hscale, vscale, format); | ||
971 | } | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h new file mode 100644 index 000000000000..a595ab643a5a --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Jernej Skrabec <jernej.skrabec@siol.net> | ||
3 | * | ||
4 | * This file is licensed under the terms of the GNU General Public | ||
5 | * License version 2. This program is licensed "as is" without any | ||
6 | * warranty of any kind, whether express or implied. | ||
7 | */ | ||
8 | |||
9 | #ifndef _SUN8I_VI_SCALER_H_ | ||
10 | #define _SUN8I_VI_SCALER_H_ | ||
11 | |||
12 | #include <drm/drm_fourcc.h> | ||
13 | #include "sun8i_mixer.h" | ||
14 | |||
15 | /* this two macros assumes 16 fractional bits which is standard in DRM */ | ||
16 | #define SUN8I_VI_SCALER_SCALE_MIN 1 | ||
17 | #define SUN8I_VI_SCALER_SCALE_MAX ((1UL << 20) - 1) | ||
18 | |||
19 | #define SUN8I_VI_SCALER_SCALE_FRAC 20 | ||
20 | #define SUN8I_VI_SCALER_PHASE_FRAC 20 | ||
21 | #define SUN8I_VI_SCALER_COEFF_COUNT 32 | ||
22 | #define SUN8I_VI_SCALER_SIZE(w, h) (((h) - 1) << 16 | ((w) - 1)) | ||
23 | |||
24 | #define SUN8I_SCALER_VSU_CTRL(ch) (0x20000 + 0x20000 * (ch) + 0x0) | ||
25 | #define SUN8I_SCALER_VSU_OUTSIZE(ch) (0x20000 + 0x20000 * (ch) + 0x40) | ||
26 | #define SUN8I_SCALER_VSU_YINSIZE(ch) (0x20000 + 0x20000 * (ch) + 0x80) | ||
27 | #define SUN8I_SCALER_VSU_YHSTEP(ch) (0x20000 + 0x20000 * (ch) + 0x88) | ||
28 | #define SUN8I_SCALER_VSU_YVSTEP(ch) (0x20000 + 0x20000 * (ch) + 0x8c) | ||
29 | #define SUN8I_SCALER_VSU_YHPHASE(ch) (0x20000 + 0x20000 * (ch) + 0x90) | ||
30 | #define SUN8I_SCALER_VSU_YVPHASE(ch) (0x20000 + 0x20000 * (ch) + 0x98) | ||
31 | #define SUN8I_SCALER_VSU_CINSIZE(ch) (0x20000 + 0x20000 * (ch) + 0xc0) | ||
32 | #define SUN8I_SCALER_VSU_CHSTEP(ch) (0x20000 + 0x20000 * (ch) + 0xc8) | ||
33 | #define SUN8I_SCALER_VSU_CVSTEP(ch) (0x20000 + 0x20000 * (ch) + 0xcc) | ||
34 | #define SUN8I_SCALER_VSU_CHPHASE(ch) (0x20000 + 0x20000 * (ch) + 0xd0) | ||
35 | #define SUN8I_SCALER_VSU_CVPHASE(ch) (0x20000 + 0x20000 * (ch) + 0xd8) | ||
36 | #define SUN8I_SCALER_VSU_YHCOEFF0(ch, i) \ | ||
37 | (0x20000 + 0x20000 * (ch) + 0x200 + 0x4 * (i)) | ||
38 | #define SUN8I_SCALER_VSU_YHCOEFF1(ch, i) \ | ||
39 | (0x20000 + 0x20000 * (ch) + 0x300 + 0x4 * (i)) | ||
40 | #define SUN8I_SCALER_VSU_YVCOEFF(ch, i) \ | ||
41 | (0x20000 + 0x20000 * (ch) + 0x400 + 0x4 * (i)) | ||
42 | #define SUN8I_SCALER_VSU_CHCOEFF0(ch, i) \ | ||
43 | (0x20000 + 0x20000 * (ch) + 0x600 + 0x4 * (i)) | ||
44 | #define SUN8I_SCALER_VSU_CHCOEFF1(ch, i) \ | ||
45 | (0x20000 + 0x20000 * (ch) + 0x700 + 0x4 * (i)) | ||
46 | #define SUN8I_SCALER_VSU_CVCOEFF(ch, i) \ | ||
47 | (0x20000 + 0x20000 * (ch) + 0x800 + 0x4 * (i)) | ||
48 | |||
49 | #define SUN8I_SCALER_VSU_CTRL_EN BIT(0) | ||
50 | #define SUN8I_SCALER_VSU_CTRL_COEFF_RDY BIT(4) | ||
51 | |||
52 | void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable); | ||
53 | void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer, | ||
54 | u32 src_w, u32 src_h, u32 dst_w, u32 dst_h, | ||
55 | u32 hscale, u32 vscale, u32 hphase, u32 vphase, | ||
56 | const struct drm_format_info *format); | ||
57 | |||
58 | #endif | ||
diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig index 2e790e7dced5..90c5bd5ef81b 100644 --- a/drivers/gpu/drm/tinydrm/Kconfig +++ b/drivers/gpu/drm/tinydrm/Kconfig | |||
@@ -12,6 +12,16 @@ menuconfig DRM_TINYDRM | |||
12 | config TINYDRM_MIPI_DBI | 12 | config TINYDRM_MIPI_DBI |
13 | tristate | 13 | tristate |
14 | 14 | ||
15 | config TINYDRM_ILI9225 | ||
16 | tristate "DRM support for ILI9225 display panels" | ||
17 | depends on DRM_TINYDRM && SPI | ||
18 | select TINYDRM_MIPI_DBI | ||
19 | help | ||
20 | DRM driver for the following Ilitek ILI9225 panels: | ||
21 | * No-name 2.2" color screen module | ||
22 | |||
23 | If M is selected the module will be called ili9225. | ||
24 | |||
15 | config TINYDRM_MI0283QT | 25 | config TINYDRM_MI0283QT |
16 | tristate "DRM support for MI0283QT" | 26 | tristate "DRM support for MI0283QT" |
17 | depends on DRM_TINYDRM && SPI | 27 | depends on DRM_TINYDRM && SPI |
diff --git a/drivers/gpu/drm/tinydrm/Makefile b/drivers/gpu/drm/tinydrm/Makefile index 0c184bd1bb59..8aeee532474f 100644 --- a/drivers/gpu/drm/tinydrm/Makefile +++ b/drivers/gpu/drm/tinydrm/Makefile | |||
@@ -4,6 +4,7 @@ obj-$(CONFIG_DRM_TINYDRM) += core/ | |||
4 | obj-$(CONFIG_TINYDRM_MIPI_DBI) += mipi-dbi.o | 4 | obj-$(CONFIG_TINYDRM_MIPI_DBI) += mipi-dbi.o |
5 | 5 | ||
6 | # Displays | 6 | # Displays |
7 | obj-$(CONFIG_TINYDRM_ILI9225) += ili9225.o | ||
7 | obj-$(CONFIG_TINYDRM_MI0283QT) += mi0283qt.o | 8 | obj-$(CONFIG_TINYDRM_MI0283QT) += mi0283qt.o |
8 | obj-$(CONFIG_TINYDRM_REPAPER) += repaper.o | 9 | obj-$(CONFIG_TINYDRM_REPAPER) += repaper.o |
9 | obj-$(CONFIG_TINYDRM_ST7586) += st7586.o | 10 | obj-$(CONFIG_TINYDRM_ST7586) += st7586.o |
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c index 1a8a57cad431..bd7b82824a34 100644 --- a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c | |||
@@ -292,71 +292,4 @@ void tinydrm_shutdown(struct tinydrm_device *tdev) | |||
292 | } | 292 | } |
293 | EXPORT_SYMBOL(tinydrm_shutdown); | 293 | EXPORT_SYMBOL(tinydrm_shutdown); |
294 | 294 | ||
295 | /** | ||
296 | * tinydrm_suspend - Suspend tinydrm | ||
297 | * @tdev: tinydrm device | ||
298 | * | ||
299 | * Used in driver PM operations to suspend tinydrm. | ||
300 | * Suspends fbdev and DRM. | ||
301 | * Resume with tinydrm_resume(). | ||
302 | * | ||
303 | * Returns: | ||
304 | * Zero on success, negative error code on failure. | ||
305 | */ | ||
306 | int tinydrm_suspend(struct tinydrm_device *tdev) | ||
307 | { | ||
308 | struct drm_atomic_state *state; | ||
309 | |||
310 | if (tdev->suspend_state) { | ||
311 | DRM_ERROR("Failed to suspend: state already set\n"); | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | drm_fbdev_cma_set_suspend_unlocked(tdev->fbdev_cma, 1); | ||
316 | state = drm_atomic_helper_suspend(tdev->drm); | ||
317 | if (IS_ERR(state)) { | ||
318 | drm_fbdev_cma_set_suspend_unlocked(tdev->fbdev_cma, 0); | ||
319 | return PTR_ERR(state); | ||
320 | } | ||
321 | |||
322 | tdev->suspend_state = state; | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | EXPORT_SYMBOL(tinydrm_suspend); | ||
327 | |||
328 | /** | ||
329 | * tinydrm_resume - Resume tinydrm | ||
330 | * @tdev: tinydrm device | ||
331 | * | ||
332 | * Used in driver PM operations to resume tinydrm. | ||
333 | * Suspend with tinydrm_suspend(). | ||
334 | * | ||
335 | * Returns: | ||
336 | * Zero on success, negative error code on failure. | ||
337 | */ | ||
338 | int tinydrm_resume(struct tinydrm_device *tdev) | ||
339 | { | ||
340 | struct drm_atomic_state *state = tdev->suspend_state; | ||
341 | int ret; | ||
342 | |||
343 | if (!state) { | ||
344 | DRM_ERROR("Failed to resume: state is not set\n"); | ||
345 | return -EINVAL; | ||
346 | } | ||
347 | |||
348 | tdev->suspend_state = NULL; | ||
349 | |||
350 | ret = drm_atomic_helper_resume(tdev->drm, state); | ||
351 | if (ret) { | ||
352 | DRM_ERROR("Error resuming state: %d\n", ret); | ||
353 | return ret; | ||
354 | } | ||
355 | |||
356 | drm_fbdev_cma_set_suspend_unlocked(tdev->fbdev_cma, 0); | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | EXPORT_SYMBOL(tinydrm_resume); | ||
361 | |||
362 | MODULE_LICENSE("GPL"); | 295 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/gpu/drm/tinydrm/ili9225.c b/drivers/gpu/drm/tinydrm/ili9225.c new file mode 100644 index 000000000000..3b766a26aa61 --- /dev/null +++ b/drivers/gpu/drm/tinydrm/ili9225.c | |||
@@ -0,0 +1,468 @@ | |||
1 | /* | ||
2 | * DRM driver for Ilitek ILI9225 panels | ||
3 | * | ||
4 | * Copyright 2017 David Lechner <david@lechnology.com> | ||
5 | * | ||
6 | * Some code copied from mipi-dbi.c | ||
7 | * Copyright 2016 Noralf Trønnes | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/delay.h> | ||
16 | #include <linux/dma-buf.h> | ||
17 | #include <linux/gpio/consumer.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/property.h> | ||
20 | #include <linux/spi/spi.h> | ||
21 | #include <video/mipi_display.h> | ||
22 | |||
23 | #include <drm/drm_gem_framebuffer_helper.h> | ||
24 | #include <drm/tinydrm/mipi-dbi.h> | ||
25 | #include <drm/tinydrm/tinydrm-helpers.h> | ||
26 | |||
27 | #define ILI9225_DRIVER_READ_CODE 0x00 | ||
28 | #define ILI9225_DRIVER_OUTPUT_CONTROL 0x01 | ||
29 | #define ILI9225_LCD_AC_DRIVING_CONTROL 0x02 | ||
30 | #define ILI9225_ENTRY_MODE 0x03 | ||
31 | #define ILI9225_DISPLAY_CONTROL_1 0x07 | ||
32 | #define ILI9225_BLANK_PERIOD_CONTROL_1 0x08 | ||
33 | #define ILI9225_FRAME_CYCLE_CONTROL 0x0b | ||
34 | #define ILI9225_INTERFACE_CONTROL 0x0c | ||
35 | #define ILI9225_OSCILLATION_CONTROL 0x0f | ||
36 | #define ILI9225_POWER_CONTROL_1 0x10 | ||
37 | #define ILI9225_POWER_CONTROL_2 0x11 | ||
38 | #define ILI9225_POWER_CONTROL_3 0x12 | ||
39 | #define ILI9225_POWER_CONTROL_4 0x13 | ||
40 | #define ILI9225_POWER_CONTROL_5 0x14 | ||
41 | #define ILI9225_VCI_RECYCLING 0x15 | ||
42 | #define ILI9225_RAM_ADDRESS_SET_1 0x20 | ||
43 | #define ILI9225_RAM_ADDRESS_SET_2 0x21 | ||
44 | #define ILI9225_WRITE_DATA_TO_GRAM 0x22 | ||
45 | #define ILI9225_SOFTWARE_RESET 0x28 | ||
46 | #define ILI9225_GATE_SCAN_CONTROL 0x30 | ||
47 | #define ILI9225_VERTICAL_SCROLL_1 0x31 | ||
48 | #define ILI9225_VERTICAL_SCROLL_2 0x32 | ||
49 | #define ILI9225_VERTICAL_SCROLL_3 0x33 | ||
50 | #define ILI9225_PARTIAL_DRIVING_POS_1 0x34 | ||
51 | #define ILI9225_PARTIAL_DRIVING_POS_2 0x35 | ||
52 | #define ILI9225_HORIZ_WINDOW_ADDR_1 0x36 | ||
53 | #define ILI9225_HORIZ_WINDOW_ADDR_2 0x37 | ||
54 | #define ILI9225_VERT_WINDOW_ADDR_1 0x38 | ||
55 | #define ILI9225_VERT_WINDOW_ADDR_2 0x39 | ||
56 | #define ILI9225_GAMMA_CONTROL_1 0x50 | ||
57 | #define ILI9225_GAMMA_CONTROL_2 0x51 | ||
58 | #define ILI9225_GAMMA_CONTROL_3 0x52 | ||
59 | #define ILI9225_GAMMA_CONTROL_4 0x53 | ||
60 | #define ILI9225_GAMMA_CONTROL_5 0x54 | ||
61 | #define ILI9225_GAMMA_CONTROL_6 0x55 | ||
62 | #define ILI9225_GAMMA_CONTROL_7 0x56 | ||
63 | #define ILI9225_GAMMA_CONTROL_8 0x57 | ||
64 | #define ILI9225_GAMMA_CONTROL_9 0x58 | ||
65 | #define ILI9225_GAMMA_CONTROL_10 0x59 | ||
66 | |||
67 | static inline int ili9225_command(struct mipi_dbi *mipi, u8 cmd, u16 data) | ||
68 | { | ||
69 | u8 par[2] = { data >> 8, data & 0xff }; | ||
70 | |||
71 | return mipi_dbi_command_buf(mipi, cmd, par, 2); | ||
72 | } | ||
73 | |||
74 | static int ili9225_fb_dirty(struct drm_framebuffer *fb, | ||
75 | struct drm_file *file_priv, unsigned int flags, | ||
76 | unsigned int color, struct drm_clip_rect *clips, | ||
77 | unsigned int num_clips) | ||
78 | { | ||
79 | struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); | ||
80 | struct tinydrm_device *tdev = fb->dev->dev_private; | ||
81 | struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); | ||
82 | bool swap = mipi->swap_bytes; | ||
83 | struct drm_clip_rect clip; | ||
84 | u16 x_start, y_start; | ||
85 | u16 x1, x2, y1, y2; | ||
86 | int ret = 0; | ||
87 | bool full; | ||
88 | void *tr; | ||
89 | |||
90 | mutex_lock(&tdev->dirty_lock); | ||
91 | |||
92 | if (!mipi->enabled) | ||
93 | goto out_unlock; | ||
94 | |||
95 | /* fbdev can flush even when we're not interested */ | ||
96 | if (tdev->pipe.plane.fb != fb) | ||
97 | goto out_unlock; | ||
98 | |||
99 | full = tinydrm_merge_clips(&clip, clips, num_clips, flags, | ||
100 | fb->width, fb->height); | ||
101 | |||
102 | DRM_DEBUG("Flushing [FB:%d] x1=%u, x2=%u, y1=%u, y2=%u\n", fb->base.id, | ||
103 | clip.x1, clip.x2, clip.y1, clip.y2); | ||
104 | |||
105 | if (!mipi->dc || !full || swap || | ||
106 | fb->format->format == DRM_FORMAT_XRGB8888) { | ||
107 | tr = mipi->tx_buf; | ||
108 | ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, &clip, swap); | ||
109 | if (ret) | ||
110 | goto out_unlock; | ||
111 | } else { | ||
112 | tr = cma_obj->vaddr; | ||
113 | } | ||
114 | |||
115 | switch (mipi->rotation) { | ||
116 | default: | ||
117 | x1 = clip.x1; | ||
118 | x2 = clip.x2 - 1; | ||
119 | y1 = clip.y1; | ||
120 | y2 = clip.y2 - 1; | ||
121 | x_start = x1; | ||
122 | y_start = y1; | ||
123 | break; | ||
124 | case 90: | ||
125 | x1 = clip.y1; | ||
126 | x2 = clip.y2 - 1; | ||
127 | y1 = fb->width - clip.x2; | ||
128 | y2 = fb->width - clip.x1 - 1; | ||
129 | x_start = x1; | ||
130 | y_start = y2; | ||
131 | break; | ||
132 | case 180: | ||
133 | x1 = fb->width - clip.x2; | ||
134 | x2 = fb->width - clip.x1 - 1; | ||
135 | y1 = fb->height - clip.y2; | ||
136 | y2 = fb->height - clip.y1 - 1; | ||
137 | x_start = x2; | ||
138 | y_start = y2; | ||
139 | break; | ||
140 | case 270: | ||
141 | x1 = fb->height - clip.y2; | ||
142 | x2 = fb->height - clip.y1 - 1; | ||
143 | y1 = clip.x1; | ||
144 | y2 = clip.x2 - 1; | ||
145 | x_start = x2; | ||
146 | y_start = y1; | ||
147 | break; | ||
148 | } | ||
149 | |||
150 | ili9225_command(mipi, ILI9225_HORIZ_WINDOW_ADDR_1, x2); | ||
151 | ili9225_command(mipi, ILI9225_HORIZ_WINDOW_ADDR_2, x1); | ||
152 | ili9225_command(mipi, ILI9225_VERT_WINDOW_ADDR_1, y2); | ||
153 | ili9225_command(mipi, ILI9225_VERT_WINDOW_ADDR_2, y1); | ||
154 | |||
155 | ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_1, x_start); | ||
156 | ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_2, y_start); | ||
157 | |||
158 | ret = mipi_dbi_command_buf(mipi, ILI9225_WRITE_DATA_TO_GRAM, tr, | ||
159 | (clip.x2 - clip.x1) * (clip.y2 - clip.y1) * 2); | ||
160 | |||
161 | out_unlock: | ||
162 | mutex_unlock(&tdev->dirty_lock); | ||
163 | |||
164 | if (ret) | ||
165 | dev_err_once(fb->dev->dev, "Failed to update display %d\n", | ||
166 | ret); | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | static const struct drm_framebuffer_funcs ili9225_fb_funcs = { | ||
172 | .destroy = drm_gem_fb_destroy, | ||
173 | .create_handle = drm_gem_fb_create_handle, | ||
174 | .dirty = ili9225_fb_dirty, | ||
175 | }; | ||
176 | |||
177 | static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, | ||
178 | struct drm_crtc_state *crtc_state) | ||
179 | { | ||
180 | struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); | ||
181 | struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); | ||
182 | struct drm_framebuffer *fb = pipe->plane.fb; | ||
183 | struct device *dev = tdev->drm->dev; | ||
184 | int ret; | ||
185 | u8 am_id; | ||
186 | |||
187 | DRM_DEBUG_KMS("\n"); | ||
188 | |||
189 | mipi_dbi_hw_reset(mipi); | ||
190 | |||
191 | /* | ||
192 | * There don't seem to be two example init sequences that match, so | ||
193 | * using the one from the popular Arduino library for this display. | ||
194 | * https://github.com/Nkawu/TFT_22_ILI9225/blob/master/src/TFT_22_ILI9225.cpp | ||
195 | */ | ||
196 | |||
197 | ret = ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0000); | ||
198 | if (ret) { | ||
199 | DRM_DEV_ERROR(dev, "Error sending command %d\n", ret); | ||
200 | return; | ||
201 | } | ||
202 | ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0000); | ||
203 | ili9225_command(mipi, ILI9225_POWER_CONTROL_3, 0x0000); | ||
204 | ili9225_command(mipi, ILI9225_POWER_CONTROL_4, 0x0000); | ||
205 | ili9225_command(mipi, ILI9225_POWER_CONTROL_5, 0x0000); | ||
206 | |||
207 | msleep(40); | ||
208 | |||
209 | ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0018); | ||
210 | ili9225_command(mipi, ILI9225_POWER_CONTROL_3, 0x6121); | ||
211 | ili9225_command(mipi, ILI9225_POWER_CONTROL_4, 0x006f); | ||
212 | ili9225_command(mipi, ILI9225_POWER_CONTROL_5, 0x495f); | ||
213 | ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0800); | ||
214 | |||
215 | msleep(10); | ||
216 | |||
217 | ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x103b); | ||
218 | |||
219 | msleep(50); | ||
220 | |||
221 | switch (mipi->rotation) { | ||
222 | default: | ||
223 | am_id = 0x30; | ||
224 | break; | ||
225 | case 90: | ||
226 | am_id = 0x18; | ||
227 | break; | ||
228 | case 180: | ||
229 | am_id = 0x00; | ||
230 | break; | ||
231 | case 270: | ||
232 | am_id = 0x28; | ||
233 | break; | ||
234 | } | ||
235 | ili9225_command(mipi, ILI9225_DRIVER_OUTPUT_CONTROL, 0x011c); | ||
236 | ili9225_command(mipi, ILI9225_LCD_AC_DRIVING_CONTROL, 0x0100); | ||
237 | ili9225_command(mipi, ILI9225_ENTRY_MODE, 0x1000 | am_id); | ||
238 | ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x0000); | ||
239 | ili9225_command(mipi, ILI9225_BLANK_PERIOD_CONTROL_1, 0x0808); | ||
240 | ili9225_command(mipi, ILI9225_FRAME_CYCLE_CONTROL, 0x1100); | ||
241 | ili9225_command(mipi, ILI9225_INTERFACE_CONTROL, 0x0000); | ||
242 | ili9225_command(mipi, ILI9225_OSCILLATION_CONTROL, 0x0d01); | ||
243 | ili9225_command(mipi, ILI9225_VCI_RECYCLING, 0x0020); | ||
244 | ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_1, 0x0000); | ||
245 | ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_2, 0x0000); | ||
246 | |||
247 | ili9225_command(mipi, ILI9225_GATE_SCAN_CONTROL, 0x0000); | ||
248 | ili9225_command(mipi, ILI9225_VERTICAL_SCROLL_1, 0x00db); | ||
249 | ili9225_command(mipi, ILI9225_VERTICAL_SCROLL_2, 0x0000); | ||
250 | ili9225_command(mipi, ILI9225_VERTICAL_SCROLL_3, 0x0000); | ||
251 | ili9225_command(mipi, ILI9225_PARTIAL_DRIVING_POS_1, 0x00db); | ||
252 | ili9225_command(mipi, ILI9225_PARTIAL_DRIVING_POS_2, 0x0000); | ||
253 | |||
254 | ili9225_command(mipi, ILI9225_GAMMA_CONTROL_1, 0x0000); | ||
255 | ili9225_command(mipi, ILI9225_GAMMA_CONTROL_2, 0x0808); | ||
256 | ili9225_command(mipi, ILI9225_GAMMA_CONTROL_3, 0x080a); | ||
257 | ili9225_command(mipi, ILI9225_GAMMA_CONTROL_4, 0x000a); | ||
258 | ili9225_command(mipi, ILI9225_GAMMA_CONTROL_5, 0x0a08); | ||
259 | ili9225_command(mipi, ILI9225_GAMMA_CONTROL_6, 0x0808); | ||
260 | ili9225_command(mipi, ILI9225_GAMMA_CONTROL_7, 0x0000); | ||
261 | ili9225_command(mipi, ILI9225_GAMMA_CONTROL_8, 0x0a00); | ||
262 | ili9225_command(mipi, ILI9225_GAMMA_CONTROL_9, 0x0710); | ||
263 | ili9225_command(mipi, ILI9225_GAMMA_CONTROL_10, 0x0710); | ||
264 | |||
265 | ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x0012); | ||
266 | |||
267 | msleep(50); | ||
268 | |||
269 | ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x1017); | ||
270 | |||
271 | mipi->enabled = true; | ||
272 | |||
273 | if (fb) | ||
274 | fb->funcs->dirty(fb, NULL, 0, 0, NULL, 0); | ||
275 | } | ||
276 | |||
277 | static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe) | ||
278 | { | ||
279 | struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); | ||
280 | struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); | ||
281 | |||
282 | DRM_DEBUG_KMS("\n"); | ||
283 | |||
284 | if (!mipi->enabled) | ||
285 | return; | ||
286 | |||
287 | ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x0000); | ||
288 | msleep(50); | ||
289 | ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0007); | ||
290 | msleep(50); | ||
291 | ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0a02); | ||
292 | |||
293 | mipi->enabled = false; | ||
294 | } | ||
295 | |||
296 | static int ili9225_dbi_command(struct mipi_dbi *mipi, u8 cmd, u8 *par, | ||
297 | size_t num) | ||
298 | { | ||
299 | struct spi_device *spi = mipi->spi; | ||
300 | unsigned int bpw = 8; | ||
301 | u32 speed_hz; | ||
302 | int ret; | ||
303 | |||
304 | gpiod_set_value_cansleep(mipi->dc, 0); | ||
305 | speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1); | ||
306 | ret = tinydrm_spi_transfer(spi, speed_hz, NULL, 8, &cmd, 1); | ||
307 | if (ret || !num) | ||
308 | return ret; | ||
309 | |||
310 | if (cmd == ILI9225_WRITE_DATA_TO_GRAM && !mipi->swap_bytes) | ||
311 | bpw = 16; | ||
312 | |||
313 | gpiod_set_value_cansleep(mipi->dc, 1); | ||
314 | speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num); | ||
315 | |||
316 | return tinydrm_spi_transfer(spi, speed_hz, NULL, bpw, par, num); | ||
317 | } | ||
318 | |||
319 | static const u32 ili9225_formats[] = { | ||
320 | DRM_FORMAT_RGB565, | ||
321 | DRM_FORMAT_XRGB8888, | ||
322 | }; | ||
323 | |||
324 | static int ili9225_init(struct device *dev, struct mipi_dbi *mipi, | ||
325 | const struct drm_simple_display_pipe_funcs *pipe_funcs, | ||
326 | struct drm_driver *driver, | ||
327 | const struct drm_display_mode *mode, | ||
328 | unsigned int rotation) | ||
329 | { | ||
330 | size_t bufsize = mode->vdisplay * mode->hdisplay * sizeof(u16); | ||
331 | struct tinydrm_device *tdev = &mipi->tinydrm; | ||
332 | int ret; | ||
333 | |||
334 | if (!mipi->command) | ||
335 | return -EINVAL; | ||
336 | |||
337 | mutex_init(&mipi->cmdlock); | ||
338 | |||
339 | mipi->tx_buf = devm_kmalloc(dev, bufsize, GFP_KERNEL); | ||
340 | if (!mipi->tx_buf) | ||
341 | return -ENOMEM; | ||
342 | |||
343 | ret = devm_tinydrm_init(dev, tdev, &ili9225_fb_funcs, driver); | ||
344 | if (ret) | ||
345 | return ret; | ||
346 | |||
347 | ret = tinydrm_display_pipe_init(tdev, pipe_funcs, | ||
348 | DRM_MODE_CONNECTOR_VIRTUAL, | ||
349 | ili9225_formats, | ||
350 | ARRAY_SIZE(ili9225_formats), mode, | ||
351 | rotation); | ||
352 | if (ret) | ||
353 | return ret; | ||
354 | |||
355 | tdev->drm->mode_config.preferred_depth = 16; | ||
356 | mipi->rotation = rotation; | ||
357 | |||
358 | drm_mode_config_reset(tdev->drm); | ||
359 | |||
360 | DRM_DEBUG_KMS("preferred_depth=%u, rotation = %u\n", | ||
361 | tdev->drm->mode_config.preferred_depth, rotation); | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = { | ||
367 | .enable = ili9225_pipe_enable, | ||
368 | .disable = ili9225_pipe_disable, | ||
369 | .update = tinydrm_display_pipe_update, | ||
370 | .prepare_fb = tinydrm_display_pipe_prepare_fb, | ||
371 | }; | ||
372 | |||
373 | static const struct drm_display_mode ili9225_mode = { | ||
374 | TINYDRM_MODE(176, 220, 35, 44), | ||
375 | }; | ||
376 | |||
377 | DEFINE_DRM_GEM_CMA_FOPS(ili9225_fops); | ||
378 | |||
379 | static struct drm_driver ili9225_driver = { | ||
380 | .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | | ||
381 | DRIVER_ATOMIC, | ||
382 | .fops = &ili9225_fops, | ||
383 | TINYDRM_GEM_DRIVER_OPS, | ||
384 | .lastclose = tinydrm_lastclose, | ||
385 | .name = "ili9225", | ||
386 | .desc = "Ilitek ILI9225", | ||
387 | .date = "20171106", | ||
388 | .major = 1, | ||
389 | .minor = 0, | ||
390 | }; | ||
391 | |||
392 | static const struct of_device_id ili9225_of_match[] = { | ||
393 | { .compatible = "ilitek,ili9225-2.2in-176x220" }, | ||
394 | {}, | ||
395 | }; | ||
396 | MODULE_DEVICE_TABLE(of, ili9225_of_match); | ||
397 | |||
398 | static const struct spi_device_id ili9225_id[] = { | ||
399 | { "ili9225-2.2in-176x220", 0 }, | ||
400 | { }, | ||
401 | }; | ||
402 | MODULE_DEVICE_TABLE(spi, ili9225_id); | ||
403 | |||
404 | static int ili9225_probe(struct spi_device *spi) | ||
405 | { | ||
406 | struct device *dev = &spi->dev; | ||
407 | struct mipi_dbi *mipi; | ||
408 | struct gpio_desc *rs; | ||
409 | u32 rotation = 0; | ||
410 | int ret; | ||
411 | |||
412 | mipi = devm_kzalloc(dev, sizeof(*mipi), GFP_KERNEL); | ||
413 | if (!mipi) | ||
414 | return -ENOMEM; | ||
415 | |||
416 | mipi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); | ||
417 | if (IS_ERR(mipi->reset)) { | ||
418 | DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); | ||
419 | return PTR_ERR(mipi->reset); | ||
420 | } | ||
421 | |||
422 | rs = devm_gpiod_get(dev, "rs", GPIOD_OUT_LOW); | ||
423 | if (IS_ERR(rs)) { | ||
424 | DRM_DEV_ERROR(dev, "Failed to get gpio 'rs'\n"); | ||
425 | return PTR_ERR(rs); | ||
426 | } | ||
427 | |||
428 | device_property_read_u32(dev, "rotation", &rotation); | ||
429 | |||
430 | ret = mipi_dbi_spi_init(spi, mipi, rs); | ||
431 | if (ret) | ||
432 | return ret; | ||
433 | |||
434 | /* override the command function set in mipi_dbi_spi_init() */ | ||
435 | mipi->command = ili9225_dbi_command; | ||
436 | |||
437 | ret = ili9225_init(&spi->dev, mipi, &ili9225_pipe_funcs, | ||
438 | &ili9225_driver, &ili9225_mode, rotation); | ||
439 | if (ret) | ||
440 | return ret; | ||
441 | |||
442 | spi_set_drvdata(spi, mipi); | ||
443 | |||
444 | return devm_tinydrm_register(&mipi->tinydrm); | ||
445 | } | ||
446 | |||
447 | static void ili9225_shutdown(struct spi_device *spi) | ||
448 | { | ||
449 | struct mipi_dbi *mipi = spi_get_drvdata(spi); | ||
450 | |||
451 | tinydrm_shutdown(&mipi->tinydrm); | ||
452 | } | ||
453 | |||
454 | static struct spi_driver ili9225_spi_driver = { | ||
455 | .driver = { | ||
456 | .name = "ili9225", | ||
457 | .owner = THIS_MODULE, | ||
458 | .of_match_table = ili9225_of_match, | ||
459 | }, | ||
460 | .id_table = ili9225_id, | ||
461 | .probe = ili9225_probe, | ||
462 | .shutdown = ili9225_shutdown, | ||
463 | }; | ||
464 | module_spi_driver(ili9225_spi_driver); | ||
465 | |||
466 | MODULE_DESCRIPTION("Ilitek ILI9225 DRM driver"); | ||
467 | MODULE_AUTHOR("David Lechner <david@lechnology.com>"); | ||
468 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c index 6a83b3093254..70ae4f76f455 100644 --- a/drivers/gpu/drm/tinydrm/mi0283qt.c +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * (at your option) any later version. | 9 | * (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <drm/drm_modeset_helper.h> | ||
12 | #include <drm/tinydrm/ili9341.h> | 13 | #include <drm/tinydrm/ili9341.h> |
13 | #include <drm/tinydrm/mipi-dbi.h> | 14 | #include <drm/tinydrm/mipi-dbi.h> |
14 | #include <drm/tinydrm/tinydrm-helpers.h> | 15 | #include <drm/tinydrm/tinydrm-helpers.h> |
@@ -231,7 +232,7 @@ static int __maybe_unused mi0283qt_pm_suspend(struct device *dev) | |||
231 | struct mipi_dbi *mipi = dev_get_drvdata(dev); | 232 | struct mipi_dbi *mipi = dev_get_drvdata(dev); |
232 | int ret; | 233 | int ret; |
233 | 234 | ||
234 | ret = tinydrm_suspend(&mipi->tinydrm); | 235 | ret = drm_mode_config_helper_suspend(mipi->tinydrm.drm); |
235 | if (ret) | 236 | if (ret) |
236 | return ret; | 237 | return ret; |
237 | 238 | ||
@@ -249,7 +250,9 @@ static int __maybe_unused mi0283qt_pm_resume(struct device *dev) | |||
249 | if (ret) | 250 | if (ret) |
250 | return ret; | 251 | return ret; |
251 | 252 | ||
252 | return tinydrm_resume(&mipi->tinydrm); | 253 | drm_mode_config_helper_resume(mipi->tinydrm.drm); |
254 | |||
255 | return 0; | ||
253 | } | 256 | } |
254 | 257 | ||
255 | static const struct dev_pm_ops mi0283qt_pm_ops = { | 258 | static const struct dev_pm_ops mi0283qt_pm_ops = { |
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c index 347f9b226f26..aa6b6ce56891 100644 --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c | |||
@@ -154,8 +154,18 @@ int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len) | |||
154 | } | 154 | } |
155 | EXPORT_SYMBOL(mipi_dbi_command_buf); | 155 | EXPORT_SYMBOL(mipi_dbi_command_buf); |
156 | 156 | ||
157 | static int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, | 157 | /** |
158 | struct drm_clip_rect *clip, bool swap) | 158 | * mipi_dbi_buf_copy - Copy a framebuffer, transforming it if necessary |
159 | * @dst: The destination buffer | ||
160 | * @fb: The source framebuffer | ||
161 | * @clip: Clipping rectangle of the area to be copied | ||
162 | * @swap: When true, swap MSB/LSB of 16-bit values | ||
163 | * | ||
164 | * Returns: | ||
165 | * Zero on success, negative error code on failure. | ||
166 | */ | ||
167 | int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, | ||
168 | struct drm_clip_rect *clip, bool swap) | ||
159 | { | 169 | { |
160 | struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); | 170 | struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); |
161 | struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; | 171 | struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; |
@@ -192,6 +202,7 @@ static int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, | |||
192 | DMA_FROM_DEVICE); | 202 | DMA_FROM_DEVICE); |
193 | return ret; | 203 | return ret; |
194 | } | 204 | } |
205 | EXPORT_SYMBOL(mipi_dbi_buf_copy); | ||
195 | 206 | ||
196 | static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, | 207 | static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, |
197 | struct drm_file *file_priv, | 208 | struct drm_file *file_priv, |
@@ -444,18 +455,23 @@ EXPORT_SYMBOL(mipi_dbi_display_is_on); | |||
444 | 455 | ||
445 | #if IS_ENABLED(CONFIG_SPI) | 456 | #if IS_ENABLED(CONFIG_SPI) |
446 | 457 | ||
447 | /* | 458 | /** |
459 | * mipi_dbi_spi_cmd_max_speed - get the maximum SPI bus speed | ||
460 | * @spi: SPI device | ||
461 | * @len: The transfer buffer length. | ||
462 | * | ||
448 | * Many controllers have a max speed of 10MHz, but can be pushed way beyond | 463 | * Many controllers have a max speed of 10MHz, but can be pushed way beyond |
449 | * that. Increase reliability by running pixel data at max speed and the rest | 464 | * that. Increase reliability by running pixel data at max speed and the rest |
450 | * at 10MHz, preventing transfer glitches from messing up the init settings. | 465 | * at 10MHz, preventing transfer glitches from messing up the init settings. |
451 | */ | 466 | */ |
452 | static u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len) | 467 | u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len) |
453 | { | 468 | { |
454 | if (len > 64) | 469 | if (len > 64) |
455 | return 0; /* use default */ | 470 | return 0; /* use default */ |
456 | 471 | ||
457 | return min_t(u32, 10000000, spi->max_speed_hz); | 472 | return min_t(u32, 10000000, spi->max_speed_hz); |
458 | } | 473 | } |
474 | EXPORT_SYMBOL(mipi_dbi_spi_cmd_max_speed); | ||
459 | 475 | ||
460 | /* | 476 | /* |
461 | * MIPI DBI Type C Option 1 | 477 | * MIPI DBI Type C Option 1 |
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 2f615b7f1c9f..2566cfbdebfb 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig | |||
@@ -772,6 +772,7 @@ config FB_VESA | |||
772 | config FB_EFI | 772 | config FB_EFI |
773 | bool "EFI-based Framebuffer Support" | 773 | bool "EFI-based Framebuffer Support" |
774 | depends on (FB = y) && !IA64 && EFI | 774 | depends on (FB = y) && !IA64 && EFI |
775 | select DRM_PANEL_ORIENTATION_QUIRKS | ||
775 | select FB_CFB_FILLRECT | 776 | select FB_CFB_FILLRECT |
776 | select FB_CFB_COPYAREA | 777 | select FB_CFB_COPYAREA |
777 | select FB_CFB_IMAGEBLIT | 778 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile index d34fd182ca68..37710316a680 100644 --- a/drivers/video/fbdev/core/Makefile +++ b/drivers/video/fbdev/core/Makefile | |||
@@ -15,9 +15,6 @@ ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION),y) | |||
15 | fb-y += fbcon_rotate.o fbcon_cw.o fbcon_ud.o \ | 15 | fb-y += fbcon_rotate.o fbcon_cw.o fbcon_ud.o \ |
16 | fbcon_ccw.o | 16 | fbcon_ccw.o |
17 | endif | 17 | endif |
18 | ifeq ($(CONFIG_DMI),y) | ||
19 | fb-y += fbcon_dmi_quirks.o | ||
20 | endif | ||
21 | endif | 18 | endif |
22 | fb-objs := $(fb-y) | 19 | fb-objs := $(fb-y) |
23 | 20 | ||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 929ca472c524..5baf7bc054e1 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c | |||
@@ -964,10 +964,13 @@ static const char *fbcon_startup(void) | |||
964 | ops->cur_blink_jiffies = HZ / 5; | 964 | ops->cur_blink_jiffies = HZ / 5; |
965 | ops->info = info; | 965 | ops->info = info; |
966 | info->fbcon_par = ops; | 966 | info->fbcon_par = ops; |
967 | if (initial_rotation != -1) | 967 | |
968 | p->con_rotate = initial_rotation; | 968 | p->con_rotate = initial_rotation; |
969 | else | 969 | if (p->con_rotate == -1) |
970 | p->con_rotate = fbcon_platform_get_rotate(info); | 970 | p->con_rotate = info->fbcon_rotate_hint; |
971 | if (p->con_rotate == -1) | ||
972 | p->con_rotate = FB_ROTATE_UR; | ||
973 | |||
971 | set_blitting_type(vc, info); | 974 | set_blitting_type(vc, info); |
972 | 975 | ||
973 | if (info->fix.type != FB_TYPE_TEXT) { | 976 | if (info->fix.type != FB_TYPE_TEXT) { |
@@ -1104,10 +1107,13 @@ static void fbcon_init(struct vc_data *vc, int init) | |||
1104 | 1107 | ||
1105 | ops = info->fbcon_par; | 1108 | ops = info->fbcon_par; |
1106 | ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms); | 1109 | ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms); |
1107 | if (initial_rotation != -1) | 1110 | |
1108 | p->con_rotate = initial_rotation; | 1111 | p->con_rotate = initial_rotation; |
1109 | else | 1112 | if (p->con_rotate == -1) |
1110 | p->con_rotate = fbcon_platform_get_rotate(info); | 1113 | p->con_rotate = info->fbcon_rotate_hint; |
1114 | if (p->con_rotate == -1) | ||
1115 | p->con_rotate = FB_ROTATE_UR; | ||
1116 | |||
1111 | set_blitting_type(vc, info); | 1117 | set_blitting_type(vc, info); |
1112 | 1118 | ||
1113 | cols = vc->vc_cols; | 1119 | cols = vc->vc_cols; |
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h index 9f7744fbc962..21912a3ba32f 100644 --- a/drivers/video/fbdev/core/fbcon.h +++ b/drivers/video/fbdev/core/fbcon.h | |||
@@ -262,10 +262,4 @@ extern void fbcon_set_rotate(struct fbcon_ops *ops); | |||
262 | #define fbcon_set_rotate(x) do {} while(0) | 262 | #define fbcon_set_rotate(x) do {} while(0) |
263 | #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ | 263 | #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ |
264 | 264 | ||
265 | #ifdef CONFIG_DMI | ||
266 | int fbcon_platform_get_rotate(struct fb_info *info); | ||
267 | #else | ||
268 | #define fbcon_platform_get_rotate(i) FB_ROTATE_UR | ||
269 | #endif /* CONFIG_DMI */ | ||
270 | |||
271 | #endif /* _VIDEO_FBCON_H */ | 265 | #endif /* _VIDEO_FBCON_H */ |
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c index 15755ce1d26c..e31a182b42bf 100644 --- a/drivers/video/fbdev/core/fbsysfs.c +++ b/drivers/video/fbdev/core/fbsysfs.c | |||
@@ -58,6 +58,7 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev) | |||
58 | info->par = p + fb_info_size; | 58 | info->par = p + fb_info_size; |
59 | 59 | ||
60 | info->device = dev; | 60 | info->device = dev; |
61 | info->fbcon_rotate_hint = -1; | ||
61 | 62 | ||
62 | #ifdef CONFIG_FB_BACKLIGHT | 63 | #ifdef CONFIG_FB_BACKLIGHT |
63 | mutex_init(&info->bl_curve_mutex); | 64 | mutex_init(&info->bl_curve_mutex); |
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c index d1bf9c2a78a7..46a4484e3da7 100644 --- a/drivers/video/fbdev/efifb.c +++ b/drivers/video/fbdev/efifb.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/screen_info.h> | 16 | #include <linux/screen_info.h> |
17 | #include <video/vga.h> | 17 | #include <video/vga.h> |
18 | #include <asm/efi.h> | 18 | #include <asm/efi.h> |
19 | #include <drm/drm_utils.h> /* For drm_get_panel_orientation_quirk */ | ||
20 | #include <drm/drm_connector.h> /* For DRM_MODE_PANEL_ORIENTATION_* */ | ||
19 | 21 | ||
20 | static bool request_mem_succeeded = false; | 22 | static bool request_mem_succeeded = false; |
21 | static bool nowc = false; | 23 | static bool nowc = false; |
@@ -157,7 +159,7 @@ static u64 bar_offset; | |||
157 | static int efifb_probe(struct platform_device *dev) | 159 | static int efifb_probe(struct platform_device *dev) |
158 | { | 160 | { |
159 | struct fb_info *info; | 161 | struct fb_info *info; |
160 | int err; | 162 | int err, orientation; |
161 | unsigned int size_vmode; | 163 | unsigned int size_vmode; |
162 | unsigned int size_remap; | 164 | unsigned int size_remap; |
163 | unsigned int size_total; | 165 | unsigned int size_total; |
@@ -329,6 +331,23 @@ static int efifb_probe(struct platform_device *dev) | |||
329 | info->fix = efifb_fix; | 331 | info->fix = efifb_fix; |
330 | info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE; | 332 | info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE; |
331 | 333 | ||
334 | orientation = drm_get_panel_orientation_quirk(efifb_defined.xres, | ||
335 | efifb_defined.yres); | ||
336 | switch (orientation) { | ||
337 | default: | ||
338 | info->fbcon_rotate_hint = FB_ROTATE_UR; | ||
339 | break; | ||
340 | case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: | ||
341 | info->fbcon_rotate_hint = FB_ROTATE_UD; | ||
342 | break; | ||
343 | case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: | ||
344 | info->fbcon_rotate_hint = FB_ROTATE_CCW; | ||
345 | break; | ||
346 | case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: | ||
347 | info->fbcon_rotate_hint = FB_ROTATE_CW; | ||
348 | break; | ||
349 | } | ||
350 | |||
332 | err = sysfs_create_groups(&dev->dev.kobj, efifb_groups); | 351 | err = sysfs_create_groups(&dev->dev.kobj, efifb_groups); |
333 | if (err) { | 352 | if (err) { |
334 | pr_err("efifb: cannot add sysfs attrs\n"); | 353 | pr_err("efifb: cannot add sysfs attrs\n"); |
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 66d6c99d15e5..f39ff52feb3b 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h | |||
@@ -176,6 +176,35 @@ enum drm_link_status { | |||
176 | }; | 176 | }; |
177 | 177 | ||
178 | /** | 178 | /** |
179 | * enum drm_panel_orientation - panel_orientation info for &drm_display_info | ||
180 | * | ||
181 | * This enum is used to track the (LCD) panel orientation. There are no | ||
182 | * separate #defines for the uapi! | ||
183 | * | ||
184 | * @DRM_MODE_PANEL_ORIENTATION_UNKNOWN: The drm driver has not provided any | ||
185 | * panel orientation information (normal | ||
186 | * for non panels) in this case the "panel | ||
187 | * orientation" connector prop will not be | ||
188 | * attached. | ||
189 | * @DRM_MODE_PANEL_ORIENTATION_NORMAL: The top side of the panel matches the | ||
190 | * top side of the device's casing. | ||
191 | * @DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: The top side of the panel matches the | ||
192 | * bottom side of the device's casing, iow | ||
193 | * the panel is mounted upside-down. | ||
194 | * @DRM_MODE_PANEL_ORIENTATION_LEFT_UP: The left side of the panel matches the | ||
195 | * top side of the device's casing. | ||
196 | * @DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: The right side of the panel matches the | ||
197 | * top side of the device's casing. | ||
198 | */ | ||
199 | enum drm_panel_orientation { | ||
200 | DRM_MODE_PANEL_ORIENTATION_UNKNOWN = -1, | ||
201 | DRM_MODE_PANEL_ORIENTATION_NORMAL = 0, | ||
202 | DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP, | ||
203 | DRM_MODE_PANEL_ORIENTATION_LEFT_UP, | ||
204 | DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, | ||
205 | }; | ||
206 | |||
207 | /** | ||
179 | * struct drm_display_info - runtime data about the connected sink | 208 | * struct drm_display_info - runtime data about the connected sink |
180 | * | 209 | * |
181 | * Describes a given display (e.g. CRT or flat panel) and its limitations. For | 210 | * Describes a given display (e.g. CRT or flat panel) and its limitations. For |
@@ -223,6 +252,15 @@ struct drm_display_info { | |||
223 | #define DRM_COLOR_FORMAT_YCRCB420 (1<<3) | 252 | #define DRM_COLOR_FORMAT_YCRCB420 (1<<3) |
224 | 253 | ||
225 | /** | 254 | /** |
255 | * @panel_orientation: Read only connector property for built-in panels, | ||
256 | * indicating the orientation of the panel vs the device's casing. | ||
257 | * drm_connector_init() sets this to DRM_MODE_PANEL_ORIENTATION_UNKNOWN. | ||
258 | * When not UNKNOWN this gets used by the drm_fb_helpers to rotate the | ||
259 | * fb to compensate and gets exported as prop to userspace. | ||
260 | */ | ||
261 | int panel_orientation; | ||
262 | |||
263 | /** | ||
226 | * @color_formats: HDMI Color formats, selects between RGB and YCrCb | 264 | * @color_formats: HDMI Color formats, selects between RGB and YCrCb |
227 | * modes. Used DRM_COLOR_FORMAT\_ defines, which are _not_ the same ones | 265 | * modes. Used DRM_COLOR_FORMAT\_ defines, which are _not_ the same ones |
228 | * as used to describe the pixel format in framebuffers, and also don't | 266 | * as used to describe the pixel format in framebuffers, and also don't |
@@ -1035,6 +1073,8 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, | |||
1035 | const struct edid *edid); | 1073 | const struct edid *edid); |
1036 | void drm_mode_connector_set_link_status_property(struct drm_connector *connector, | 1074 | void drm_mode_connector_set_link_status_property(struct drm_connector *connector, |
1037 | uint64_t link_status); | 1075 | uint64_t link_status); |
1076 | int drm_connector_init_panel_orientation_property( | ||
1077 | struct drm_connector *connector, int width, int height); | ||
1038 | 1078 | ||
1039 | /** | 1079 | /** |
1040 | * struct drm_tile_group - Tile group metadata | 1080 | * struct drm_tile_group - Tile group metadata |
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 877e5b395c02..1494b12a984a 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h | |||
@@ -48,6 +48,7 @@ struct drm_fb_helper_crtc { | |||
48 | struct drm_mode_set mode_set; | 48 | struct drm_mode_set mode_set; |
49 | struct drm_display_mode *desired_mode; | 49 | struct drm_display_mode *desired_mode; |
50 | int x, y; | 50 | int x, y; |
51 | int rotation; | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | /** | 54 | /** |
@@ -159,6 +160,13 @@ struct drm_fb_helper { | |||
159 | int connector_count; | 160 | int connector_count; |
160 | int connector_info_alloc_count; | 161 | int connector_info_alloc_count; |
161 | /** | 162 | /** |
163 | * @sw_rotations: | ||
164 | * Bitmask of all rotations requested for panel-orientation which | ||
165 | * could not be handled in hardware. If only one bit is set | ||
166 | * fbdev->fbcon_rotate_hint gets set to the requested rotation. | ||
167 | */ | ||
168 | int sw_rotations; | ||
169 | /** | ||
162 | * @connector_info: | 170 | * @connector_info: |
163 | * | 171 | * |
164 | * Array of per-connector information. Do not iterate directly, but use | 172 | * Array of per-connector information. Do not iterate directly, but use |
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 5306ebd537b2..a0afeb591dcb 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h | |||
@@ -735,6 +735,13 @@ struct drm_mode_config { | |||
735 | */ | 735 | */ |
736 | struct drm_property *non_desktop_property; | 736 | struct drm_property *non_desktop_property; |
737 | 737 | ||
738 | /** | ||
739 | * @panel_orientation_property: Optional connector property indicating | ||
740 | * how the lcd-panel is mounted inside the casing (e.g. normal or | ||
741 | * upside-down). | ||
742 | */ | ||
743 | struct drm_property *panel_orientation_property; | ||
744 | |||
738 | /* dumb ioctl parameters */ | 745 | /* dumb ioctl parameters */ |
739 | uint32_t preferred_depth, prefer_shadow; | 746 | uint32_t preferred_depth, prefer_shadow; |
740 | 747 | ||
@@ -760,6 +767,15 @@ struct drm_mode_config { | |||
760 | /* cursor size */ | 767 | /* cursor size */ |
761 | uint32_t cursor_width, cursor_height; | 768 | uint32_t cursor_width, cursor_height; |
762 | 769 | ||
770 | /** | ||
771 | * @suspend_state: | ||
772 | * | ||
773 | * Atomic state when suspended. | ||
774 | * Set by drm_mode_config_helper_suspend() and cleared by | ||
775 | * drm_mode_config_helper_resume(). | ||
776 | */ | ||
777 | struct drm_atomic_state *suspend_state; | ||
778 | |||
763 | const struct drm_mode_config_helper_funcs *helper_private; | 779 | const struct drm_mode_config_helper_funcs *helper_private; |
764 | }; | 780 | }; |
765 | 781 | ||
diff --git a/include/drm/drm_modeset_helper.h b/include/drm/drm_modeset_helper.h index cb0ec92e11e6..efa337f03129 100644 --- a/include/drm/drm_modeset_helper.h +++ b/include/drm/drm_modeset_helper.h | |||
@@ -34,4 +34,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_device *dev, | |||
34 | int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | 34 | int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, |
35 | const struct drm_crtc_funcs *funcs); | 35 | const struct drm_crtc_funcs *funcs); |
36 | 36 | ||
37 | int drm_mode_config_helper_suspend(struct drm_device *dev); | ||
38 | int drm_mode_config_helper_resume(struct drm_device *dev); | ||
39 | |||
37 | #endif | 40 | #endif |
diff --git a/include/drm/drm_utils.h b/include/drm/drm_utils.h new file mode 100644 index 000000000000..a803988d8579 --- /dev/null +++ b/include/drm/drm_utils.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* SPDX-License-Identifier: MIT */ | ||
2 | /* | ||
3 | * Function prototypes for misc. drm utility functions. | ||
4 | * Specifically this file is for function prototypes for functions which | ||
5 | * may also be used outside of drm code (e.g. in fbdev drivers). | ||
6 | * | ||
7 | * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com> | ||
8 | */ | ||
9 | |||
10 | #ifndef __DRM_UTILS_H__ | ||
11 | #define __DRM_UTILS_H__ | ||
12 | |||
13 | int drm_get_panel_orientation_quirk(int width, int height); | ||
14 | |||
15 | #endif | ||
diff --git a/include/drm/tinydrm/mipi-dbi.h b/include/drm/tinydrm/mipi-dbi.h index 83346ddb9dba..5d0e82b36eaf 100644 --- a/include/drm/tinydrm/mipi-dbi.h +++ b/include/drm/tinydrm/mipi-dbi.h | |||
@@ -72,10 +72,12 @@ void mipi_dbi_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
72 | void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe); | 72 | void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe); |
73 | void mipi_dbi_hw_reset(struct mipi_dbi *mipi); | 73 | void mipi_dbi_hw_reset(struct mipi_dbi *mipi); |
74 | bool mipi_dbi_display_is_on(struct mipi_dbi *mipi); | 74 | bool mipi_dbi_display_is_on(struct mipi_dbi *mipi); |
75 | u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len); | ||
75 | 76 | ||
76 | int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val); | 77 | int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val); |
77 | int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len); | 78 | int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len); |
78 | 79 | int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, | |
80 | struct drm_clip_rect *clip, bool swap); | ||
79 | /** | 81 | /** |
80 | * mipi_dbi_command - MIPI DCS command with optional parameter(s) | 82 | * mipi_dbi_command - MIPI DCS command with optional parameter(s) |
81 | * @mipi: MIPI structure | 83 | * @mipi: MIPI structure |
diff --git a/include/drm/tinydrm/tinydrm.h b/include/drm/tinydrm/tinydrm.h index 423828922e5a..03cd9d72308c 100644 --- a/include/drm/tinydrm/tinydrm.h +++ b/include/drm/tinydrm/tinydrm.h | |||
@@ -20,7 +20,6 @@ | |||
20 | * @pipe: Display pipe structure | 20 | * @pipe: Display pipe structure |
21 | * @dirty_lock: Serializes framebuffer flushing | 21 | * @dirty_lock: Serializes framebuffer flushing |
22 | * @fbdev_cma: CMA fbdev structure | 22 | * @fbdev_cma: CMA fbdev structure |
23 | * @suspend_state: Atomic state when suspended | ||
24 | * @fb_funcs: Framebuffer functions used when creating framebuffers | 23 | * @fb_funcs: Framebuffer functions used when creating framebuffers |
25 | */ | 24 | */ |
26 | struct tinydrm_device { | 25 | struct tinydrm_device { |
@@ -28,7 +27,6 @@ struct tinydrm_device { | |||
28 | struct drm_simple_display_pipe pipe; | 27 | struct drm_simple_display_pipe pipe; |
29 | struct mutex dirty_lock; | 28 | struct mutex dirty_lock; |
30 | struct drm_fbdev_cma *fbdev_cma; | 29 | struct drm_fbdev_cma *fbdev_cma; |
31 | struct drm_atomic_state *suspend_state; | ||
32 | const struct drm_framebuffer_funcs *fb_funcs; | 30 | const struct drm_framebuffer_funcs *fb_funcs; |
33 | }; | 31 | }; |
34 | 32 | ||
@@ -93,8 +91,6 @@ int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev, | |||
93 | struct drm_driver *driver); | 91 | struct drm_driver *driver); |
94 | int devm_tinydrm_register(struct tinydrm_device *tdev); | 92 | int devm_tinydrm_register(struct tinydrm_device *tdev); |
95 | void tinydrm_shutdown(struct tinydrm_device *tdev); | 93 | void tinydrm_shutdown(struct tinydrm_device *tdev); |
96 | int tinydrm_suspend(struct tinydrm_device *tdev); | ||
97 | int tinydrm_resume(struct tinydrm_device *tdev); | ||
98 | 94 | ||
99 | void tinydrm_display_pipe_update(struct drm_simple_display_pipe *pipe, | 95 | void tinydrm_display_pipe_update(struct drm_simple_display_pipe *pipe, |
100 | struct drm_plane_state *old_state); | 96 | struct drm_plane_state *old_state); |
diff --git a/include/linux/fb.h b/include/linux/fb.h index bc24e48e396d..d1e5bed39140 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -465,6 +465,11 @@ struct fb_info { | |||
465 | atomic_t count; | 465 | atomic_t count; |
466 | int node; | 466 | int node; |
467 | int flags; | 467 | int flags; |
468 | /* | ||
469 | * -1 by default, set to a FB_ROTATE_* value by the driver, if it knows | ||
470 | * a lcd is not mounted upright and fbcon should rotate to compensate. | ||
471 | */ | ||
472 | int fbcon_rotate_hint; | ||
468 | struct mutex lock; /* Lock for open/release/ioctl funcs */ | 473 | struct mutex lock; /* Lock for open/release/ioctl funcs */ |
469 | struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ | 474 | struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ |
470 | struct fb_var_screeninfo var; /* Current var */ | 475 | struct fb_var_screeninfo var; /* Current var */ |