Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'drm-misc-next-2024-06-27' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next

drm-misc-next for 6.11:

UAPI Changes:

Cross-subsystem Changes:

Core Changes:
- panic: Monochrome logo support, Various fixes
- ttm: Improve the number of page faults on some platforms, Fix test
build breakage with PREEMPT_RT, more test coverage and various test
improvements

Driver Changes:
- Add missing MODULE_DESCRIPTION where needed
- ipu-v3: Various fixes
- vc4: Monochrome TV support
- bridge:
- analogix_dp: Various improvements and reworks, handle AUX
transfers timeout
- tc358767: Fix DRM_BRIDGE_ATTACH_NO_CONNECTOR, Fix clock
calculations
- panels:
- More transitions to mipi_dsi wrapped functions
- New panels: Lincoln Technologies LCD197, Ortustech COM35H3P70ULC,

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Maxime Ripard <mripard@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240627-congenial-pistachio-nyala-848cf4@houat

+3864 -1244
+5
Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml
··· 71 71 - const: iahb 72 72 - const: venci 73 73 74 + power-domains: 75 + maxItems: 1 76 + description: phandle to the associated power domain 77 + 74 78 resets: 75 79 minItems: 3 76 80 ··· 133 129 reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy"; 134 130 clocks = <&clk_isfr>, <&clk_iahb>, <&clk_venci>; 135 131 clock-names = "isfr", "iahb", "venci"; 132 + power-domains = <&pd_vpu>; 136 133 #address-cells = <1>; 137 134 #size-cells = <0>; 138 135
+13
Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml
··· 45 45 - const: isfr 46 46 additionalItems: true 47 47 48 + ddc-i2c-bus: 49 + $ref: /schemas/types.yaml#/definitions/phandle 50 + deprecated: true 51 + description: 52 + The HDMI DDC bus can be connected to either a system I2C master or the 53 + functionally-reduced I2C master contained in the DWC HDMI. When connected 54 + to a system I2C master this property contains a phandle to that I2C 55 + master controller. 56 + 57 + This property is deprecated, the system I2C master controller should 58 + be referenced through the ddc-i2c-bus property of the HDMI connector 59 + node. 60 + 48 61 interrupts: 49 62 maxItems: 1 50 63
+1 -1
Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml
··· 25 25 26 26 reg: 27 27 enum: 28 - - 0x68 29 28 - 0x0f 29 + - 0x68 30 30 description: | 31 31 i2c address of the bridge, 0x68 or 0x0f, depending on bootstrap pins 32 32
-8
Documentation/devicetree/bindings/display/imx/fsl,imx6-hdmi.yaml
··· 31 31 clock-names: 32 32 maxItems: 2 33 33 34 - ddc-i2c-bus: 35 - $ref: /schemas/types.yaml#/definitions/phandle 36 - description: 37 - The HDMI DDC bus can be connected to either a system I2C master or the 38 - functionally-reduced I2C master contained in the DWC HDMI. When connected 39 - to a system I2C master this property contains a phandle to that I2C 40 - master controller. 41 - 42 34 gpr: 43 35 $ref: /schemas/types.yaml#/definitions/phandle 44 36 description:
+63
Documentation/devicetree/bindings/display/panel/ilitek,ili9806e.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/display/panel/ilitek,ili9806e.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Ilitek ILI9806E based MIPI-DSI panels 8 + 9 + maintainers: 10 + - Michael Walle <mwalle@kernel.org> 11 + 12 + allOf: 13 + - $ref: panel-common.yaml# 14 + 15 + properties: 16 + compatible: 17 + items: 18 + - enum: 19 + - ortustech,com35h3p70ulc 20 + - const: ilitek,ili9806e 21 + 22 + reg: 23 + maxItems: 1 24 + 25 + vdd-supply: true 26 + vccio-supply: true 27 + 28 + required: 29 + - compatible 30 + - reg 31 + - vdd-supply 32 + - vccio-supply 33 + - reset-gpios 34 + - backlight 35 + - port 36 + 37 + unevaluatedProperties: false 38 + 39 + examples: 40 + - | 41 + #include <dt-bindings/gpio/gpio.h> 42 + 43 + dsi { 44 + #address-cells = <1>; 45 + #size-cells = <0>; 46 + 47 + panel@0 { 48 + compatible = "ortustech,com35h3p70ulc", "ilitek,ili9806e"; 49 + reg = <0>; 50 + vdd-supply = <&reg_vdd_panel>; 51 + vccio-supply = <&reg_vccio_panel>; 52 + reset-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>; 53 + backlight = <&backlight>; 54 + 55 + port { 56 + panel_in: endpoint { 57 + remote-endpoint = <&dsi_out>; 58 + }; 59 + }; 60 + }; 61 + }; 62 + 63 + ...
+2
Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
··· 46 46 - lg,ld070wx3-sl01 47 47 # LG Corporation 5" HD TFT LCD panel 48 48 - lg,lh500wx1-sd03 49 + # Lincoln LCD197 5" 1080x1920 LCD panel 50 + - lincolntech,lcd197 49 51 # One Stop Displays OSD101T2587-53TS 10.1" 1920x1200 panel 50 52 - osddisplays,osd101t2587-53ts 51 53 # Panasonic 10" WUXGA TFT LCD panel
-8
Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
··· 70 70 - vpll 71 71 - ref 72 72 73 - ddc-i2c-bus: 74 - $ref: /schemas/types.yaml#/definitions/phandle 75 - description: 76 - The HDMI DDC bus can be connected to either a system I2C master or the 77 - functionally-reduced I2C master contained in the DWC HDMI. When connected 78 - to a system I2C master this property contains a phandle to that I2C 79 - master controller. 80 - 81 73 phys: 82 74 maxItems: 1 83 75 description: The HDMI PHY
+7 -1
MAINTAINERS
··· 6899 6899 F: Documentation/devicetree/bindings/display/panel/ilitek,ili9805.yaml 6900 6900 F: drivers/gpu/drm/panel/panel-ilitek-ili9805.c 6901 6901 6902 + DRM DRIVER FOR ILITEK ILI9806E PANELS 6903 + M: Michael Walle <mwalle@kernel.org> 6904 + S: Maintained 6905 + F: drivers/gpu/drm/panel/panel-ilitek-ili9806e.c 6906 + 6902 6907 DRM DRIVER FOR JADARD JD9365DA-H3 MIPI-DSI LCD PANELS 6903 6908 M: Jagan Teki <jagan@edgeble.ai> 6904 6909 S: Maintained ··· 7524 7519 7525 7520 DRM DRIVERS FOR VC4 7526 7521 M: Maxime Ripard <mripard@kernel.org> 7522 + M: Dave Stevenson <dave.stevenson@raspberrypi.com> 7523 + R: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com> 7527 7524 S: Supported 7528 - T: git git://github.com/anholt/linux 7529 7525 T: git https://gitlab.freedesktop.org/drm/misc/kernel.git 7530 7526 F: Documentation/devicetree/bindings/display/brcm,bcm2835-*.yaml 7531 7527 F: drivers/gpu/drm/vc4/
+2 -2
drivers/gpu/drm/Kconfig
··· 108 108 config DRM_PANIC 109 109 bool "Display a user-friendly message when a kernel panic occurs" 110 110 depends on DRM && !(FRAMEBUFFER_CONSOLE && VT_CONSOLE) 111 - select DRM_KMS_HELPER 112 111 select FONT_SUPPORT 113 112 help 114 113 Enable a drm panic handler, which will display a user-friendly message ··· 137 138 If in doubt, say "N". 138 139 139 140 config DRM_PANIC_SCREEN 140 - string "Panic screen formater" 141 + string "Panic screen formatter" 141 142 default "user" 142 143 depends on DRM_PANIC 143 144 help ··· 247 248 default n 248 249 depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST) 249 250 select DRM_TTM 251 + select DRM_BUDDY 250 252 select DRM_EXPORT_FOR_TESTS if m 251 253 select DRM_KUNIT_TEST_HELPERS 252 254 default KUNIT_ALL_TESTS
+40 -5
drivers/gpu/drm/ast/ast_mode.c
··· 45 45 #include <drm/drm_managed.h> 46 46 #include <drm/drm_panic.h> 47 47 #include <drm/drm_probe_helper.h> 48 - #include <drm/drm_simple_kms_helper.h> 49 48 50 49 #include "ast_ddc.h" 51 50 #include "ast_drv.h" ··· 1358 1359 } 1359 1360 1360 1361 /* 1362 + * VGA Encoder 1363 + */ 1364 + 1365 + static const struct drm_encoder_funcs ast_vga_encoder_funcs = { 1366 + .destroy = drm_encoder_cleanup, 1367 + }; 1368 + 1369 + /* 1361 1370 * VGA Connector 1362 1371 */ 1363 1372 ··· 1418 1411 struct drm_connector *connector = &ast->output.vga.connector; 1419 1412 int ret; 1420 1413 1421 - ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC); 1414 + ret = drm_encoder_init(dev, encoder, &ast_vga_encoder_funcs, 1415 + DRM_MODE_ENCODER_DAC, NULL); 1422 1416 if (ret) 1423 1417 return ret; 1424 1418 encoder->possible_crtcs = drm_crtc_mask(crtc); ··· 1434 1426 1435 1427 return 0; 1436 1428 } 1429 + 1430 + /* 1431 + * SIL164 Encoder 1432 + */ 1433 + 1434 + static const struct drm_encoder_funcs ast_sil164_encoder_funcs = { 1435 + .destroy = drm_encoder_cleanup, 1436 + }; 1437 1437 1438 1438 /* 1439 1439 * SIL164 Connector ··· 1496 1480 struct drm_connector *connector = &ast->output.sil164.connector; 1497 1481 int ret; 1498 1482 1499 - ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS); 1483 + ret = drm_encoder_init(dev, encoder, &ast_sil164_encoder_funcs, 1484 + DRM_MODE_ENCODER_TMDS, NULL); 1500 1485 if (ret) 1501 1486 return ret; 1502 1487 encoder->possible_crtcs = drm_crtc_mask(crtc); ··· 1512 1495 1513 1496 return 0; 1514 1497 } 1498 + 1499 + /* 1500 + * DP501 Encoder 1501 + */ 1502 + 1503 + static const struct drm_encoder_funcs ast_dp501_encoder_funcs = { 1504 + .destroy = drm_encoder_cleanup, 1505 + }; 1515 1506 1516 1507 /* 1517 1508 * DP501 Connector ··· 1603 1578 struct drm_connector *connector = &ast->output.dp501.connector; 1604 1579 int ret; 1605 1580 1606 - ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS); 1581 + ret = drm_encoder_init(dev, encoder, &ast_dp501_encoder_funcs, 1582 + DRM_MODE_ENCODER_TMDS, NULL); 1607 1583 if (ret) 1608 1584 return ret; 1609 1585 encoder->possible_crtcs = drm_crtc_mask(crtc); ··· 1619 1593 1620 1594 return 0; 1621 1595 } 1596 + 1597 + /* 1598 + * ASPEED Display-Port Encoder 1599 + */ 1600 + 1601 + static const struct drm_encoder_funcs ast_astdp_encoder_funcs = { 1602 + .destroy = drm_encoder_cleanup, 1603 + }; 1622 1604 1623 1605 /* 1624 1606 * ASPEED Display-Port Connector ··· 1722 1688 struct drm_connector *connector = &ast->output.astdp.connector; 1723 1689 int ret; 1724 1690 1725 - ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS); 1691 + ret = drm_encoder_init(dev, encoder, &ast_astdp_encoder_funcs, 1692 + DRM_MODE_ENCODER_TMDS, NULL); 1726 1693 if (ret) 1727 1694 return ret; 1728 1695 encoder->possible_crtcs = drm_crtc_mask(crtc);
+87 -110
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
··· 41 41 struct device_node *node; 42 42 }; 43 43 44 - static int analogix_dp_init_dp(struct analogix_dp_device *dp) 44 + static void analogix_dp_init_dp(struct analogix_dp_device *dp) 45 45 { 46 - int ret; 47 - 48 46 analogix_dp_reset(dp); 49 47 50 48 analogix_dp_swreset(dp); ··· 54 56 analogix_dp_enable_sw_function(dp); 55 57 56 58 analogix_dp_config_interrupt(dp); 57 - ret = analogix_dp_init_analog_func(dp); 58 - if (ret) 59 - return ret; 60 59 61 60 analogix_dp_init_hpd(dp); 62 61 analogix_dp_init_aux(dp); 63 - return 0; 64 62 } 65 63 66 64 static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) ··· 231 237 static int analogix_dp_link_start(struct analogix_dp_device *dp) 232 238 { 233 239 u8 buf[4]; 234 - int lane, lane_count, pll_tries, retval; 240 + int lane, lane_count, retval; 235 241 236 242 lane_count = dp->link_train.lane_count; 237 243 ··· 243 249 244 250 /* Set link rate and count as you want to establish*/ 245 251 analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); 252 + retval = analogix_dp_wait_pll_locked(dp); 253 + if (retval) { 254 + DRM_DEV_ERROR(dp->dev, "Wait for pll lock failed %d\n", retval); 255 + return retval; 256 + } 257 + /* 258 + * MACRO_RST must be applied after the PLL_LOCK to avoid 259 + * the DP inter pair skew issue for at least 10 us 260 + */ 261 + analogix_dp_reset_macro(dp); 246 262 analogix_dp_set_lane_count(dp, dp->link_train.lane_count); 247 263 248 264 /* Setup RX configuration */ ··· 274 270 DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | 275 271 DP_TRAIN_PRE_EMPH_LEVEL_0; 276 272 analogix_dp_set_lane_link_training(dp); 277 - 278 - /* Wait for PLL lock */ 279 - pll_tries = 0; 280 - while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { 281 - if (pll_tries == DP_TIMEOUT_LOOP_COUNT) { 282 - dev_err(dp->dev, "Wait for PLL lock timed out\n"); 283 - return -ETIMEDOUT; 284 - } 285 - 286 - pll_tries++; 287 - usleep_range(90, 120); 288 - } 289 273 290 274 /* Set training pattern 1 */ 291 275 analogix_dp_set_training_pattern(dp, TRAINING_PTN1); ··· 560 568 int retval = 0; 561 569 bool training_finished = false; 562 570 563 - /* 564 - * MACRO_RST must be applied after the PLL_LOCK to avoid 565 - * the DP inter pair skew issue for at least 10 us 566 - */ 567 - analogix_dp_reset_macro(dp); 568 - 569 571 /* Initialize by reading RX's DPCD */ 570 572 analogix_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); 571 573 analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); ··· 624 638 { 625 639 int ret; 626 640 u8 link_align, link_status[2]; 627 - enum pll_status status; 628 - 629 - analogix_dp_reset_macro(dp); 630 641 631 642 analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); 632 - analogix_dp_set_lane_count(dp, dp->link_train.lane_count); 633 - analogix_dp_set_lane_link_training(dp); 634 - 635 - ret = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status, 636 - status != PLL_UNLOCKED, 120, 637 - 120 * DP_TIMEOUT_LOOP_COUNT); 643 + ret = analogix_dp_wait_pll_locked(dp); 638 644 if (ret) { 639 645 DRM_DEV_ERROR(dp->dev, "Wait for pll lock failed %d\n", ret); 640 646 return ret; 641 647 } 648 + 649 + /* 650 + * MACRO_RST must be applied after the PLL_LOCK to avoid 651 + * the DP inter pair skew issue for at least 10 us 652 + */ 653 + analogix_dp_reset_macro(dp); 654 + analogix_dp_set_lane_count(dp, dp->link_train.lane_count); 655 + analogix_dp_set_lane_link_training(dp); 642 656 643 657 /* source Set training pattern 1 */ 644 658 analogix_dp_set_training_pattern(dp, TRAINING_PTN1); ··· 708 722 analogix_dp_config_video_slave_mode(dp); 709 723 710 724 analogix_dp_set_video_color_format(dp); 711 - 712 - if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { 713 - dev_err(dp->dev, "PLL is not locked yet.\n"); 714 - return -EINVAL; 715 - } 716 725 717 726 for (;;) { 718 727 timeout_loop++; ··· 1232 1251 1233 1252 pm_runtime_get_sync(dp->dev); 1234 1253 1235 - ret = clk_prepare_enable(dp->clock); 1236 - if (ret < 0) { 1237 - DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret); 1238 - goto out_dp_clk_pre; 1239 - } 1240 - 1241 - if (dp->plat_data->power_on_start) 1242 - dp->plat_data->power_on_start(dp->plat_data); 1243 - 1244 - phy_power_on(dp->phy); 1245 - 1246 - ret = analogix_dp_init_dp(dp); 1254 + ret = analogix_dp_init_analog_func(dp); 1247 1255 if (ret) 1248 - goto out_dp_init; 1256 + return ret; 1249 1257 1250 1258 /* 1251 1259 * According to DP spec v1.3 chap 3.5.1.2 Link Training, ··· 1253 1283 goto out_dp_init; 1254 1284 } 1255 1285 1256 - if (dp->plat_data->power_on_end) 1257 - dp->plat_data->power_on_end(dp->plat_data); 1258 - 1259 1286 enable_irq(dp->irq); 1260 1287 return 0; 1261 1288 1262 1289 out_dp_init: 1263 - phy_power_off(dp->phy); 1264 - if (dp->plat_data->power_off) 1265 - dp->plat_data->power_off(dp->plat_data); 1266 - clk_disable_unprepare(dp->clock); 1267 - out_dp_clk_pre: 1268 1290 pm_runtime_put_sync(dp->dev); 1269 1291 1270 1292 return ret; ··· 1319 1357 1320 1358 disable_irq(dp->irq); 1321 1359 1322 - if (dp->plat_data->power_off) 1323 - dp->plat_data->power_off(dp->plat_data); 1324 - 1325 1360 analogix_dp_set_analog_power_down(dp, POWER_ALL, 1); 1326 - phy_power_off(dp->phy); 1327 - 1328 - clk_disable_unprepare(dp->clock); 1329 1361 1330 1362 pm_runtime_put_sync(dp->dev); 1331 1363 ··· 1610 1654 return ERR_CAST(dp->clock); 1611 1655 } 1612 1656 1613 - clk_prepare_enable(dp->clock); 1614 - 1615 1657 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1616 1658 1617 1659 dp->reg_base = devm_ioremap_resource(&pdev->dev, res); ··· 1671 1717 } 1672 1718 EXPORT_SYMBOL_GPL(analogix_dp_probe); 1673 1719 1720 + int analogix_dp_suspend(struct analogix_dp_device *dp) 1721 + { 1722 + phy_power_off(dp->phy); 1723 + 1724 + if (dp->plat_data->power_off) 1725 + dp->plat_data->power_off(dp->plat_data); 1726 + 1727 + clk_disable_unprepare(dp->clock); 1728 + 1729 + return 0; 1730 + } 1731 + EXPORT_SYMBOL_GPL(analogix_dp_suspend); 1732 + 1733 + int analogix_dp_resume(struct analogix_dp_device *dp) 1734 + { 1735 + int ret; 1736 + 1737 + ret = clk_prepare_enable(dp->clock); 1738 + if (ret < 0) { 1739 + DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret); 1740 + return ret; 1741 + } 1742 + 1743 + if (dp->plat_data->power_on) 1744 + dp->plat_data->power_on(dp->plat_data); 1745 + 1746 + phy_power_on(dp->phy); 1747 + 1748 + analogix_dp_init_dp(dp); 1749 + 1750 + return 0; 1751 + } 1752 + EXPORT_SYMBOL_GPL(analogix_dp_resume); 1753 + 1674 1754 int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev) 1675 1755 { 1676 1756 int ret; ··· 1712 1724 dp->drm_dev = drm_dev; 1713 1725 dp->encoder = dp->plat_data->encoder; 1714 1726 1727 + if (IS_ENABLED(CONFIG_PM)) { 1728 + pm_runtime_use_autosuspend(dp->dev); 1729 + pm_runtime_set_autosuspend_delay(dp->dev, 100); 1730 + pm_runtime_enable(dp->dev); 1731 + } else { 1732 + ret = analogix_dp_resume(dp); 1733 + if (ret) 1734 + return ret; 1735 + } 1736 + 1715 1737 dp->aux.name = "DP-AUX"; 1716 1738 dp->aux.transfer = analogix_dpaux_transfer; 1717 1739 dp->aux.dev = dp->dev; 1718 1740 dp->aux.drm_dev = drm_dev; 1719 1741 1720 1742 ret = drm_dp_aux_register(&dp->aux); 1721 - if (ret) 1722 - return ret; 1723 - 1724 - pm_runtime_use_autosuspend(dp->dev); 1725 - pm_runtime_set_autosuspend_delay(dp->dev, 100); 1726 - pm_runtime_enable(dp->dev); 1743 + if (ret) { 1744 + DRM_ERROR("failed to register AUX (%d)\n", ret); 1745 + goto err_disable_pm_runtime; 1746 + } 1727 1747 1728 1748 ret = analogix_dp_create_bridge(drm_dev, dp); 1729 1749 if (ret) { 1730 1750 DRM_ERROR("failed to create bridge (%d)\n", ret); 1731 - goto err_disable_pm_runtime; 1751 + goto err_unregister_aux; 1732 1752 } 1733 1753 1734 1754 return 0; 1735 1755 1736 - err_disable_pm_runtime: 1737 - pm_runtime_dont_use_autosuspend(dp->dev); 1738 - pm_runtime_disable(dp->dev); 1756 + err_unregister_aux: 1739 1757 drm_dp_aux_unregister(&dp->aux); 1758 + err_disable_pm_runtime: 1759 + if (IS_ENABLED(CONFIG_PM)) { 1760 + pm_runtime_dont_use_autosuspend(dp->dev); 1761 + pm_runtime_disable(dp->dev); 1762 + } else { 1763 + analogix_dp_suspend(dp); 1764 + } 1740 1765 1741 1766 return ret; 1742 1767 } ··· 1766 1765 } 1767 1766 1768 1767 drm_dp_aux_unregister(&dp->aux); 1769 - pm_runtime_dont_use_autosuspend(dp->dev); 1770 - pm_runtime_disable(dp->dev); 1768 + 1769 + if (IS_ENABLED(CONFIG_PM)) { 1770 + pm_runtime_dont_use_autosuspend(dp->dev); 1771 + pm_runtime_disable(dp->dev); 1772 + } else { 1773 + analogix_dp_suspend(dp); 1774 + } 1771 1775 } 1772 1776 EXPORT_SYMBOL_GPL(analogix_dp_unbind); 1773 - 1774 - void analogix_dp_remove(struct analogix_dp_device *dp) 1775 - { 1776 - clk_disable_unprepare(dp->clock); 1777 - } 1778 - EXPORT_SYMBOL_GPL(analogix_dp_remove); 1779 - 1780 - #ifdef CONFIG_PM 1781 - int analogix_dp_suspend(struct analogix_dp_device *dp) 1782 - { 1783 - clk_disable_unprepare(dp->clock); 1784 - return 0; 1785 - } 1786 - EXPORT_SYMBOL_GPL(analogix_dp_suspend); 1787 - 1788 - int analogix_dp_resume(struct analogix_dp_device *dp) 1789 - { 1790 - int ret; 1791 - 1792 - ret = clk_prepare_enable(dp->clock); 1793 - if (ret < 0) { 1794 - DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret); 1795 - return ret; 1796 - } 1797 - 1798 - return 0; 1799 - } 1800 - EXPORT_SYMBOL_GPL(analogix_dp_resume); 1801 - #endif 1802 1777 1803 1778 int analogix_dp_start_crc(struct drm_connector *connector) 1804 1779 {
+1 -6
drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
··· 95 95 CEA 96 96 }; 97 97 98 - enum pll_status { 99 - PLL_UNLOCKED, 100 - PLL_LOCKED 101 - }; 102 - 103 98 enum clock_recovery_m_value_type { 104 99 CALCULATED_M, 105 100 REGISTER_M ··· 186 191 void analogix_dp_config_interrupt(struct analogix_dp_device *dp); 187 192 void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp); 188 193 void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp); 189 - enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp); 194 + int analogix_dp_wait_pll_locked(struct analogix_dp_device *dp); 190 195 void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable); 191 196 void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, 192 197 enum analog_power_block block,
+14 -24
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
··· 217 217 writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK); 218 218 } 219 219 220 - enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp) 220 + int analogix_dp_wait_pll_locked(struct analogix_dp_device *dp) 221 221 { 222 - u32 reg; 222 + u32 val; 223 223 224 - reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL); 225 - if (reg & PLL_LOCK) 226 - return PLL_LOCKED; 227 - else 228 - return PLL_UNLOCKED; 224 + return readl_poll_timeout(dp->reg_base + ANALOGIX_DP_DEBUG_CTL, val, 225 + val & PLL_LOCK, 120, 226 + 120 * DP_TIMEOUT_LOOP_COUNT); 229 227 } 230 228 231 229 void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable) ··· 354 356 int analogix_dp_init_analog_func(struct analogix_dp_device *dp) 355 357 { 356 358 u32 reg; 357 - int timeout_loop = 0; 358 359 359 360 analogix_dp_set_analog_power_down(dp, POWER_ALL, 0); 360 361 ··· 365 368 writel(reg, dp->reg_base + ANALOGIX_DP_DEBUG_CTL); 366 369 367 370 /* Power up PLL */ 368 - if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { 369 - analogix_dp_set_pll_power_down(dp, 0); 370 - 371 - while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { 372 - timeout_loop++; 373 - if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { 374 - dev_err(dp->dev, "failed to get pll lock status\n"); 375 - return -ETIMEDOUT; 376 - } 377 - usleep_range(10, 20); 378 - } 379 - } 371 + analogix_dp_set_pll_power_down(dp, 0); 380 372 381 373 /* Enable Serdes FIFO function and Link symbol clock domain module */ 382 374 reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); ··· 924 938 struct drm_dp_aux_msg *msg) 925 939 { 926 940 u32 reg; 927 - u32 status_reg; 928 941 u8 *buffer = msg->buffer; 929 942 unsigned int i; 930 943 int ret; ··· 1010 1025 1011 1026 /* Clear interrupt source for AUX CH access error */ 1012 1027 reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); 1013 - status_reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA); 1014 - if ((reg & AUX_ERR) || (status_reg & AUX_STATUS_MASK)) { 1028 + if ((reg & AUX_ERR)) { 1029 + u32 aux_status = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA) & 1030 + AUX_STATUS_MASK; 1031 + 1015 1032 writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA); 1016 1033 1034 + if (aux_status == AUX_STATUS_TIMEOUT_ERROR) 1035 + return -ETIMEDOUT; 1036 + 1017 1037 dev_warn(dp->dev, "AUX CH error happened: %#x (%d)\n", 1018 - status_reg & AUX_STATUS_MASK, !!(reg & AUX_ERR)); 1038 + aux_status, !!(reg & AUX_ERR)); 1019 1039 goto aux_error; 1020 1040 } 1021 1041
+9
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
··· 361 361 /* ANALOGIX_DP_AUX_CH_STA */ 362 362 #define AUX_BUSY (0x1 << 4) 363 363 #define AUX_STATUS_MASK (0xf << 0) 364 + #define AUX_STATUS_OK (0x0 << 0) 365 + #define AUX_STATUS_NACK_ERROR (0x1 << 0) 366 + #define AUX_STATUS_TIMEOUT_ERROR (0x2 << 0) 367 + #define AUX_STATUS_UNKNOWN_ERROR (0x3 << 0) 368 + #define AUX_STATUS_MUCH_DEFER_ERROR (0x4 << 0) 369 + #define AUX_STATUS_TX_SHORT_ERROR (0x5 << 0) 370 + #define AUX_STATUS_RX_SHORT_ERROR (0x6 << 0) 371 + #define AUX_STATUS_NACK_WITHOUT_M_ERROR (0x7 << 0) 372 + #define AUX_STATUS_I2C_NACK_ERROR (0x8 << 0) 364 373 365 374 /* ANALOGIX_DP_AUX_CH_DEFER_CTL */ 366 375 #define DEFER_CTRL_EN (0x1 << 7)
+80 -32
drivers/gpu/drm/bridge/tc358767.c
··· 382 382 383 383 /* HPD pin number (0 or 1) or -ENODEV */ 384 384 int hpd_pin; 385 - 386 - /* Number of pixels to subtract from a line due to pixel clock delta */ 387 - u32 line_pixel_subtract; 388 385 }; 389 386 390 387 static inline struct tc_data *aux_to_tc(struct drm_dp_aux *a) ··· 577 580 return 0; 578 581 } 579 582 580 - static u32 div64_round_up(u64 v, u32 d) 583 + static int tc_pxl_pll_calc(struct tc_data *tc, u32 refclk, u32 pixelclock, 584 + int *out_best_pixelclock, u32 *out_pxl_pllparam) 581 585 { 582 - return div_u64(v + d - 1, d); 583 - } 584 - 585 - static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) 586 - { 587 - int ret; 588 586 int i_pre, best_pre = 1; 589 587 int i_post, best_post = 1; 590 588 int div, best_div = 1; ··· 658 666 return -EINVAL; 659 667 } 660 668 661 - tc->line_pixel_subtract = tc->mode.htotal - 662 - div64_round_up(tc->mode.htotal * (u64)best_pixelclock, pixelclock); 663 - 664 - dev_dbg(tc->dev, "PLL: got %d, delta %d (subtract %d px)\n", best_pixelclock, 665 - best_delta, tc->line_pixel_subtract); 669 + dev_dbg(tc->dev, "PLL: got %d, delta %d\n", best_pixelclock, best_delta); 666 670 dev_dbg(tc->dev, "PLL: %d / %d / %d * %d / %d\n", refclk, 667 671 ext_div[best_pre], best_div, best_mul, ext_div[best_post]); 668 672 ··· 671 683 if (best_mul == 128) 672 684 best_mul = 0; 673 685 674 - /* Power up PLL and switch to bypass */ 675 - ret = regmap_write(tc->regmap, PXL_PLLCTRL, PLLBYP | PLLEN); 676 - if (ret) 677 - return ret; 678 - 679 686 pxl_pllparam = vco_hi << 24; /* For PLL VCO >= 300 MHz = 1 */ 680 687 pxl_pllparam |= ext_div[best_pre] << 20; /* External Pre-divider */ 681 688 pxl_pllparam |= ext_div[best_post] << 16; /* External Post-divider */ 682 689 pxl_pllparam |= IN_SEL_REFCLK; /* Use RefClk as PLL input */ 683 690 pxl_pllparam |= best_div << 8; /* Divider for PLL RefClk */ 684 691 pxl_pllparam |= best_mul; /* Multiplier for PLL */ 692 + 693 + if (out_best_pixelclock) 694 + *out_best_pixelclock = best_pixelclock; 695 + 696 + if (out_pxl_pllparam) 697 + *out_pxl_pllparam = pxl_pllparam; 698 + 699 + return 0; 700 + } 701 + 702 + static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) 703 + { 704 + u32 pxl_pllparam = 0; 705 + int ret; 706 + 707 + ret = tc_pxl_pll_calc(tc, refclk, pixelclock, NULL, &pxl_pllparam); 708 + if (ret) 709 + return ret; 710 + 711 + /* Power up PLL and switch to bypass */ 712 + ret = regmap_write(tc->regmap, PXL_PLLCTRL, PLLBYP | PLLEN); 713 + if (ret) 714 + return ret; 685 715 686 716 ret = regmap_write(tc->regmap, PXL_PLLPARAM, pxl_pllparam); 687 717 if (ret) ··· 738 732 static int tc_set_syspllparam(struct tc_data *tc) 739 733 { 740 734 unsigned long rate; 741 - u32 pllparam = SYSCLK_SEL_LSCLK | LSCLK_DIV_2; 735 + u32 pllparam = SYSCLK_SEL_LSCLK | LSCLK_DIV_1; 742 736 743 737 rate = clk_get_rate(tc->refclk); 744 738 switch (rate) { ··· 901 895 dev_dbg(tc->dev, "V margin %d,%d sync %d\n", 902 896 upper_margin, lower_margin, vsync_len); 903 897 dev_dbg(tc->dev, "total: %dx%d\n", mode->htotal, mode->vtotal); 904 - 905 - if (right_margin > tc->line_pixel_subtract) { 906 - right_margin -= tc->line_pixel_subtract; 907 - } else { 908 - dev_err(tc->dev, "Bridge pixel clock too slow for mode\n"); 909 - right_margin = 0; 910 - } 911 898 912 899 /* 913 900 * LCD Ctl Frame Size ··· 1356 1357 u32 value; 1357 1358 int ret; 1358 1359 1359 - regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 25); 1360 - regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 25); 1361 - regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 25); 1362 - regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 25); 1360 + regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 5); 1361 + regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 5); 1362 + regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 5); 1363 + regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 5); 1363 1364 regmap_write(tc->regmap, PPI_D0S_ATMR, 0); 1364 1365 regmap_write(tc->regmap, PPI_D1S_ATMR, 0); 1365 1366 regmap_write(tc->regmap, PPI_TX_RX_TA, TTA_GET | TTA_SURE); ··· 1605 1606 struct drm_crtc_state *crtc_state, 1606 1607 struct drm_connector_state *conn_state) 1607 1608 { 1609 + struct tc_data *tc = bridge_to_tc(bridge); 1610 + int adjusted_clock = 0; 1611 + int ret; 1612 + 1613 + ret = tc_pxl_pll_calc(tc, clk_get_rate(tc->refclk), 1614 + crtc_state->mode.clock * 1000, 1615 + &adjusted_clock, NULL); 1616 + if (ret) 1617 + return ret; 1618 + 1619 + crtc_state->adjusted_mode.clock = adjusted_clock / 1000; 1620 + 1608 1621 /* DSI->DPI interface clock limitation: upto 100 MHz */ 1609 1622 if (crtc_state->adjusted_mode.clock > 100000) 1610 1623 return -EINVAL; ··· 1629 1618 struct drm_crtc_state *crtc_state, 1630 1619 struct drm_connector_state *conn_state) 1631 1620 { 1621 + struct tc_data *tc = bridge_to_tc(bridge); 1622 + int adjusted_clock = 0; 1623 + int ret; 1624 + 1625 + ret = tc_pxl_pll_calc(tc, clk_get_rate(tc->refclk), 1626 + crtc_state->mode.clock * 1000, 1627 + &adjusted_clock, NULL); 1628 + if (ret) 1629 + return ret; 1630 + 1631 + crtc_state->adjusted_mode.clock = adjusted_clock / 1000; 1632 + 1632 1633 /* DPI->(e)DP interface clock limitation: upto 154 MHz */ 1633 1634 if (crtc_state->adjusted_mode.clock > 154000) 1634 1635 return -EINVAL; ··· 1843 1820 } 1844 1821 1845 1822 #define MAX_INPUT_SEL_FORMATS 1 1823 + #define MAX_OUTPUT_SEL_FORMATS 1 1846 1824 1847 1825 static u32 * 1848 1826 tc_dpi_atomic_get_input_bus_fmts(struct drm_bridge *bridge, ··· 1867 1843 *num_input_fmts = 1; 1868 1844 1869 1845 return input_fmts; 1846 + } 1847 + 1848 + static u32 * 1849 + tc_edp_atomic_get_output_bus_fmts(struct drm_bridge *bridge, 1850 + struct drm_bridge_state *bridge_state, 1851 + struct drm_crtc_state *crtc_state, 1852 + struct drm_connector_state *conn_state, 1853 + unsigned int *num_output_fmts) 1854 + { 1855 + u32 *output_fmts; 1856 + 1857 + *num_output_fmts = 0; 1858 + 1859 + output_fmts = kcalloc(MAX_OUTPUT_SEL_FORMATS, sizeof(*output_fmts), 1860 + GFP_KERNEL); 1861 + if (!output_fmts) 1862 + return NULL; 1863 + 1864 + output_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; 1865 + *num_output_fmts = 1; 1866 + 1867 + return output_fmts; 1870 1868 } 1871 1869 1872 1870 static const struct drm_bridge_funcs tc_dpi_bridge_funcs = { ··· 1917 1871 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, 1918 1872 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, 1919 1873 .atomic_reset = drm_atomic_helper_bridge_reset, 1874 + .atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt, 1875 + .atomic_get_output_bus_fmts = tc_edp_atomic_get_output_bus_fmts, 1920 1876 }; 1921 1877 1922 1878 static bool tc_readable_reg(struct device *dev, unsigned int reg)
+3 -3
drivers/gpu/drm/display/drm_hdmi_state_helper.c
··· 716 716 EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_audio_infoframe); 717 717 718 718 /** 719 - * drm_atomic_helper_connector_hdmi_disable_audio_infoframe - Stop sending the Audio Infoframe 719 + * drm_atomic_helper_connector_hdmi_clear_audio_infoframe - Stop sending the Audio Infoframe 720 720 * @connector: A pointer to the HDMI connector 721 721 * 722 722 * This function is meant for HDMI connector drivers to stop sending their ··· 727 727 * Zero on success, error code on failure. 728 728 */ 729 729 int 730 - drm_atomic_helper_connector_hdmi_disable_audio_infoframe(struct drm_connector *connector) 730 + drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *connector) 731 731 { 732 732 struct drm_connector_hdmi_infoframe *infoframe = 733 733 &connector->hdmi.infoframes.audio; ··· 749 749 750 750 return ret; 751 751 } 752 - EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_disable_audio_infoframe); 752 + EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_clear_audio_infoframe);
+61 -10
drivers/gpu/drm/drm_panic.c
··· 7 7 */ 8 8 9 9 #include <linux/font.h> 10 + #include <linux/init.h> 10 11 #include <linux/iosys-map.h> 11 12 #include <linux/kdebug.h> 12 13 #include <linux/kmsg_dump.h> 14 + #include <linux/linux_logo.h> 13 15 #include <linux/list.h> 16 + #include <linux/math.h> 14 17 #include <linux/module.h> 18 + #include <linux/overflow.h> 15 19 #include <linux/printk.h> 16 20 #include <linux/types.h> 17 21 18 22 #include <drm/drm_drv.h> 19 - #include <drm/drm_format_helper.h> 20 23 #include <drm/drm_fourcc.h> 21 24 #include <drm/drm_framebuffer.h> 22 25 #include <drm/drm_modeset_helper_vtables.h> ··· 81 78 PANIC_LINE("Please reboot your computer."), 82 79 }; 83 80 84 - static const struct drm_panic_line logo[] = { 81 + static const struct drm_panic_line logo_ascii[] = { 85 82 PANIC_LINE(" .--. _"), 86 83 PANIC_LINE(" |o_o | | |"), 87 84 PANIC_LINE(" |:_/ | | |"), ··· 90 87 PANIC_LINE(" /'\\_ _/`\\ (_)"), 91 88 PANIC_LINE(" \\___)=(___/"), 92 89 }; 90 + 91 + #if defined(CONFIG_LOGO) && !defined(MODULE) 92 + static const struct linux_logo *logo_mono; 93 + 94 + static int drm_panic_setup_logo(void) 95 + { 96 + const struct linux_logo *logo = fb_find_logo(1); 97 + const unsigned char *logo_data; 98 + struct linux_logo *logo_dup; 99 + 100 + if (!logo || logo->type != LINUX_LOGO_MONO) 101 + return 0; 102 + 103 + /* The logo is __init, so we must make a copy for later use */ 104 + logo_data = kmemdup(logo->data, 105 + size_mul(DIV_ROUND_UP(logo->width, BITS_PER_BYTE), logo->height), 106 + GFP_KERNEL); 107 + if (!logo_data) 108 + return -ENOMEM; 109 + 110 + logo_dup = kmemdup(logo, sizeof(*logo), GFP_KERNEL); 111 + if (!logo_dup) { 112 + kfree(logo_data); 113 + return -ENOMEM; 114 + } 115 + 116 + logo_dup->data = logo_data; 117 + logo_mono = logo_dup; 118 + 119 + return 0; 120 + } 121 + 122 + device_initcall(drm_panic_setup_logo); 123 + #else 124 + #define logo_mono ((const struct linux_logo *)NULL) 125 + #endif 93 126 94 127 /* 95 128 * Color conversion ··· 486 447 static void draw_panic_static_user(struct drm_scanout_buffer *sb) 487 448 { 488 449 size_t msg_lines = ARRAY_SIZE(panic_msg); 489 - size_t logo_lines = ARRAY_SIZE(logo); 450 + size_t logo_ascii_lines = ARRAY_SIZE(logo_ascii); 490 451 u32 fg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_FOREGROUND_COLOR, sb->format->format); 491 452 u32 bg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_BACKGROUND_COLOR, sb->format->format); 492 453 const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL); 493 454 struct drm_rect r_screen, r_logo, r_msg; 455 + unsigned int logo_width, logo_height; 494 456 495 457 if (!font) 496 458 return; 497 459 498 460 r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height); 499 461 500 - r_logo = DRM_RECT_INIT(0, 0, 501 - get_max_line_len(logo, logo_lines) * font->width, 502 - logo_lines * font->height); 462 + if (logo_mono) { 463 + logo_width = logo_mono->width; 464 + logo_height = logo_mono->height; 465 + } else { 466 + logo_width = get_max_line_len(logo_ascii, logo_ascii_lines) * font->width; 467 + logo_height = logo_ascii_lines * font->height; 468 + } 469 + 470 + r_logo = DRM_RECT_INIT(0, 0, logo_width, logo_height); 503 471 r_msg = DRM_RECT_INIT(0, 0, 504 472 min(get_max_line_len(panic_msg, msg_lines) * font->width, sb->width), 505 473 min(msg_lines * font->height, sb->height)); ··· 517 471 /* Fill with the background color, and draw text on top */ 518 472 drm_panic_fill(sb, &r_screen, bg_color); 519 473 520 - if ((r_msg.x1 >= drm_rect_width(&r_logo) || r_msg.y1 >= drm_rect_height(&r_logo)) && 521 - drm_rect_width(&r_logo) < sb->width && drm_rect_height(&r_logo) < sb->height) { 522 - draw_txt_rectangle(sb, font, logo, logo_lines, false, &r_logo, fg_color); 474 + if ((r_msg.x1 >= logo_width || r_msg.y1 >= logo_height) && 475 + logo_width <= sb->width && logo_height <= sb->height) { 476 + if (logo_mono) 477 + drm_panic_blit(sb, &r_logo, logo_mono->data, DIV_ROUND_UP(logo_width, 8), 478 + fg_color); 479 + else 480 + draw_txt_rectangle(sb, font, logo_ascii, logo_ascii_lines, false, &r_logo, 481 + fg_color); 523 482 } 524 483 draw_txt_rectangle(sb, font, panic_msg, msg_lines, true, &r_msg, fg_color); 525 484 } ··· 633 582 634 583 static void draw_panic_plane(struct drm_plane *plane) 635 584 { 636 - struct drm_scanout_buffer sb; 585 + struct drm_scanout_buffer sb = { }; 637 586 int ret; 638 587 unsigned long flags; 639 588
+1 -4
drivers/gpu/drm/exynos/exynos_dp.c
··· 233 233 /* The remote port can be either a panel or a bridge */ 234 234 dp->plat_data.panel = panel; 235 235 dp->plat_data.dev_type = EXYNOS_DP; 236 - dp->plat_data.power_on_start = exynos_dp_poweron; 236 + dp->plat_data.power_on = exynos_dp_poweron; 237 237 dp->plat_data.power_off = exynos_dp_poweroff; 238 238 dp->plat_data.attach = exynos_dp_bridge_attach; 239 239 dp->plat_data.get_modes = exynos_dp_get_modes; ··· 251 251 252 252 static void exynos_dp_remove(struct platform_device *pdev) 253 253 { 254 - struct exynos_dp_device *dp = platform_get_drvdata(pdev); 255 - 256 254 component_del(&pdev->dev, &exynos_dp_ops); 257 - analogix_dp_remove(dp->adp); 258 255 } 259 256 260 257 static int exynos_dp_suspend(struct device *dev)
+1
drivers/gpu/drm/mediatek/Kconfig
··· 7 7 depends on HAVE_ARM_SMCCC 8 8 depends on OF 9 9 depends on MTK_MMSYS 10 + select DRM_GEM_DMA_HELPER if DRM_FBDEV_EMULATION 10 11 select DRM_KMS_HELPER 11 12 select DRM_MIPI_DSI 12 13 select DRM_PANEL
+20
drivers/gpu/drm/panel/Kconfig
··· 205 205 Say Y if you want to enable support for panels based on the 206 206 Ilitek ILI9805 controller. 207 207 208 + config DRM_PANEL_ILITEK_ILI9806E 209 + tristate "Ilitek ILI9806E-based panels" 210 + depends on OF 211 + depends on DRM_MIPI_DSI 212 + depends on BACKLIGHT_CLASS_DEVICE 213 + help 214 + Say Y if you want to enable support for panels based on the 215 + Ilitek ILI9806E controller. 216 + 208 217 config DRM_PANEL_ILITEK_ILI9881C 209 218 tristate "Ilitek ILI9881C-based panels" 210 219 depends on OF ··· 336 327 TFT-LCD modules. The panel has a 1536x2048 resolution and uses 337 328 24 bit RGB per pixel. It provides a MIPI DSI interface to 338 329 the host and has a built-in LED backlight. 330 + 331 + config DRM_PANEL_LINCOLNTECH_LCD197 332 + tristate "Lincoln Technologies lcd197 panel" 333 + depends on OF 334 + depends on DRM_MIPI_DSI 335 + depends on BACKLIGHT_CLASS_DEVICE 336 + help 337 + Say Y here if you want to enable support for lincolntech lcd197 338 + TFT-LCD modules. The panel has a 1080x1920 resolution and uses 339 + 24 bit RGB per pixel. It provides a MIPI DSI interface to 340 + the host. 339 341 340 342 config DRM_PANEL_LG_LB035Q02 341 343 tristate "LG LB035Q024573 RGB panel"
+2
drivers/gpu/drm/panel/Makefile
··· 21 21 obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o 22 22 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o 23 23 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9805) += panel-ilitek-ili9805.o 24 + obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9806E) += panel-ilitek-ili9806e.o 24 25 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o 25 26 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9882T) += panel-ilitek-ili9882t.o 26 27 obj-$(CONFIG_DRM_PANEL_INNOLUX_EJ030NA) += panel-innolux-ej030na.o ··· 34 33 obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o 35 34 obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o 36 35 obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o 36 + obj-$(CONFIG_DRM_PANEL_LINCOLNTECH_LCD197) += panel-lincolntech-lcd197.o 37 37 obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o 38 38 obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o 39 39 obj-$(CONFIG_DRM_PANEL_LG_SW43408) += panel-lg-sw43408.o
+57 -79
drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c
··· 33 33 usleep_range(15000, 16000); 34 34 } 35 35 36 - static int tm5p5_nt35596_on(struct tm5p5_nt35596 *ctx) 36 + static void tm5p5_nt35596_on(struct mipi_dsi_multi_context *dsi_ctx) 37 37 { 38 - struct mipi_dsi_device *dsi = ctx->dsi; 38 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xff, 0x05); 39 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfb, 0x01); 40 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc5, 0x31); 41 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xff, 0x04); 42 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x01, 0x84); 43 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x05, 0x25); 44 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x06, 0x01); 45 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x07, 0x20); 46 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x08, 0x06); 47 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x09, 0x08); 48 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0a, 0x10); 49 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0b, 0x10); 50 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0c, 0x10); 51 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0d, 0x14); 52 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0e, 0x14); 53 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0f, 0x14); 54 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x10, 0x14); 55 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x11, 0x14); 56 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x12, 0x14); 57 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x17, 0xf3); 58 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0xc0); 59 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x19, 0xc0); 60 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1a, 0xc0); 61 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1b, 0xb3); 62 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1c, 0xb3); 63 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1d, 0xb3); 64 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1e, 0xb3); 65 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1f, 0xb3); 66 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x20, 0xb3); 67 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfb, 0x01); 68 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xff, 0x00); 69 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfb, 0x01); 70 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x35, 0x01); 71 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd3, 0x06); 72 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd4, 0x04); 73 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x5e, 0x0d); 74 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x11, 0x00); 39 75 40 - mipi_dsi_generic_write_seq(dsi, 0xff, 0x05); 41 - mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01); 42 - mipi_dsi_generic_write_seq(dsi, 0xc5, 0x31); 43 - mipi_dsi_generic_write_seq(dsi, 0xff, 0x04); 44 - mipi_dsi_generic_write_seq(dsi, 0x01, 0x84); 45 - mipi_dsi_generic_write_seq(dsi, 0x05, 0x25); 46 - mipi_dsi_generic_write_seq(dsi, 0x06, 0x01); 47 - mipi_dsi_generic_write_seq(dsi, 0x07, 0x20); 48 - mipi_dsi_generic_write_seq(dsi, 0x08, 0x06); 49 - mipi_dsi_generic_write_seq(dsi, 0x09, 0x08); 50 - mipi_dsi_generic_write_seq(dsi, 0x0a, 0x10); 51 - mipi_dsi_generic_write_seq(dsi, 0x0b, 0x10); 52 - mipi_dsi_generic_write_seq(dsi, 0x0c, 0x10); 53 - mipi_dsi_generic_write_seq(dsi, 0x0d, 0x14); 54 - mipi_dsi_generic_write_seq(dsi, 0x0e, 0x14); 55 - mipi_dsi_generic_write_seq(dsi, 0x0f, 0x14); 56 - mipi_dsi_generic_write_seq(dsi, 0x10, 0x14); 57 - mipi_dsi_generic_write_seq(dsi, 0x11, 0x14); 58 - mipi_dsi_generic_write_seq(dsi, 0x12, 0x14); 59 - mipi_dsi_generic_write_seq(dsi, 0x17, 0xf3); 60 - mipi_dsi_generic_write_seq(dsi, 0x18, 0xc0); 61 - mipi_dsi_generic_write_seq(dsi, 0x19, 0xc0); 62 - mipi_dsi_generic_write_seq(dsi, 0x1a, 0xc0); 63 - mipi_dsi_generic_write_seq(dsi, 0x1b, 0xb3); 64 - mipi_dsi_generic_write_seq(dsi, 0x1c, 0xb3); 65 - mipi_dsi_generic_write_seq(dsi, 0x1d, 0xb3); 66 - mipi_dsi_generic_write_seq(dsi, 0x1e, 0xb3); 67 - mipi_dsi_generic_write_seq(dsi, 0x1f, 0xb3); 68 - mipi_dsi_generic_write_seq(dsi, 0x20, 0xb3); 69 - mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01); 70 - mipi_dsi_generic_write_seq(dsi, 0xff, 0x00); 71 - mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01); 72 - mipi_dsi_generic_write_seq(dsi, 0x35, 0x01); 73 - mipi_dsi_generic_write_seq(dsi, 0xd3, 0x06); 74 - mipi_dsi_generic_write_seq(dsi, 0xd4, 0x04); 75 - mipi_dsi_generic_write_seq(dsi, 0x5e, 0x0d); 76 - mipi_dsi_generic_write_seq(dsi, 0x11, 0x00); 77 - msleep(100); 78 - mipi_dsi_generic_write_seq(dsi, 0x29, 0x00); 79 - mipi_dsi_generic_write_seq(dsi, 0x53, 0x24); 76 + mipi_dsi_msleep(dsi_ctx, 100); 80 77 81 - return 0; 78 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x29, 0x00); 79 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x53, 0x24); 82 80 } 83 81 84 - static int tm5p5_nt35596_off(struct tm5p5_nt35596 *ctx) 82 + static void tm5p5_nt35596_off(struct mipi_dsi_multi_context *dsi_ctx) 85 83 { 86 - struct mipi_dsi_device *dsi = ctx->dsi; 87 - struct device *dev = &dsi->dev; 88 - int ret; 84 + mipi_dsi_dcs_set_display_off_multi(dsi_ctx); 89 85 90 - ret = mipi_dsi_dcs_set_display_off(dsi); 91 - if (ret < 0) { 92 - dev_err(dev, "Failed to set display off: %d\n", ret); 93 - return ret; 94 - } 95 - msleep(60); 86 + mipi_dsi_msleep(dsi_ctx, 60); 96 87 97 - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 98 - if (ret < 0) { 99 - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); 100 - return ret; 101 - } 88 + mipi_dsi_dcs_enter_sleep_mode_multi(dsi_ctx); 102 89 103 - mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x01); 104 - 105 - return 0; 90 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x4f, 0x01); 106 91 } 107 92 108 93 static int tm5p5_nt35596_prepare(struct drm_panel *panel) 109 94 { 110 95 struct tm5p5_nt35596 *ctx = to_tm5p5_nt35596(panel); 111 - struct device *dev = &ctx->dsi->dev; 112 - int ret; 96 + struct mipi_dsi_multi_context dsi_ctx = {.dsi = ctx->dsi}; 113 97 114 - ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 115 - if (ret < 0) { 116 - dev_err(dev, "Failed to enable regulators: %d\n", ret); 117 - return ret; 118 - } 98 + dsi_ctx.accum_err = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 99 + if (dsi_ctx.accum_err) 100 + return dsi_ctx.accum_err; 119 101 120 102 tm5p5_nt35596_reset(ctx); 121 103 122 - ret = tm5p5_nt35596_on(ctx); 123 - if (ret < 0) { 124 - dev_err(dev, "Failed to initialize panel: %d\n", ret); 104 + tm5p5_nt35596_on(&dsi_ctx); 105 + 106 + if (dsi_ctx.accum_err) { 125 107 gpiod_set_value_cansleep(ctx->reset_gpio, 0); 126 108 regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), 127 109 ctx->supplies); 128 - return ret; 129 110 } 130 111 131 - return 0; 112 + return dsi_ctx.accum_err; 132 113 } 133 114 134 115 static int tm5p5_nt35596_unprepare(struct drm_panel *panel) 135 116 { 136 117 struct tm5p5_nt35596 *ctx = to_tm5p5_nt35596(panel); 137 - struct device *dev = &ctx->dsi->dev; 138 - int ret; 118 + struct mipi_dsi_multi_context dsi_ctx = {.dsi = ctx->dsi}; 139 119 140 - ret = tm5p5_nt35596_off(ctx); 141 - if (ret < 0) 142 - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); 120 + tm5p5_nt35596_off(&dsi_ctx); 143 121 144 122 gpiod_set_value_cansleep(ctx->reset_gpio, 0); 145 123 regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), 146 124 ctx->supplies); 147 125 148 - return 0; 126 + return dsi_ctx.accum_err; 149 127 } 150 128 151 129 static const struct drm_display_mode tm5p5_nt35596_mode = {
+402
drivers/gpu/drm/panel/panel-ilitek-ili9806e.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/delay.h> 4 + #include <linux/device.h> 5 + #include <linux/err.h> 6 + #include <linux/errno.h> 7 + #include <linux/gpio/consumer.h> 8 + #include <linux/kernel.h> 9 + #include <linux/mod_devicetable.h> 10 + #include <linux/module.h> 11 + #include <linux/property.h> 12 + #include <linux/regulator/consumer.h> 13 + 14 + #include <drm/drm_mipi_dsi.h> 15 + #include <drm/drm_modes.h> 16 + #include <drm/drm_panel.h> 17 + #include <drm/drm_probe_helper.h> 18 + 19 + #include <video/mipi_display.h> 20 + 21 + struct panel_desc { 22 + const struct drm_display_mode *display_mode; 23 + unsigned long mode_flags; 24 + enum mipi_dsi_pixel_format format; 25 + unsigned int lanes; 26 + void (*init_sequence)(struct mipi_dsi_multi_context *ctx); 27 + }; 28 + 29 + struct ili9806e_panel { 30 + struct drm_panel panel; 31 + struct mipi_dsi_device *dsi; 32 + struct gpio_desc *reset_gpio; 33 + struct regulator_bulk_data supplies[2]; 34 + const struct panel_desc *desc; 35 + enum drm_panel_orientation orientation; 36 + }; 37 + 38 + static const char * const regulator_names[] = { 39 + "vdd", 40 + "vccio", 41 + }; 42 + 43 + static inline struct ili9806e_panel *to_ili9806e_panel(struct drm_panel *panel) 44 + { 45 + return container_of(panel, struct ili9806e_panel, panel); 46 + } 47 + 48 + static int ili9806e_power_on(struct ili9806e_panel *ctx) 49 + { 50 + struct mipi_dsi_device *dsi = ctx->dsi; 51 + int ret; 52 + 53 + gpiod_set_value(ctx->reset_gpio, 1); 54 + 55 + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 56 + if (ret < 0) { 57 + dev_err(&dsi->dev, "regulator bulk enable failed: %d\n", ret); 58 + return ret; 59 + } 60 + 61 + usleep_range(10000, 20000); 62 + gpiod_set_value(ctx->reset_gpio, 0); 63 + usleep_range(10000, 20000); 64 + 65 + return 0; 66 + } 67 + 68 + static int ili9806e_power_off(struct ili9806e_panel *ctx) 69 + { 70 + struct mipi_dsi_device *dsi = ctx->dsi; 71 + int ret; 72 + 73 + gpiod_set_value(ctx->reset_gpio, 1); 74 + 75 + ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 76 + if (ret) 77 + dev_err(&dsi->dev, "regulator bulk disable failed: %d\n", ret); 78 + 79 + return ret; 80 + } 81 + 82 + static int ili9806e_on(struct ili9806e_panel *ili9806e) 83 + { 84 + struct mipi_dsi_multi_context ctx = { .dsi = ili9806e->dsi }; 85 + 86 + if (ili9806e->desc->init_sequence) 87 + ili9806e->desc->init_sequence(&ctx); 88 + 89 + mipi_dsi_dcs_exit_sleep_mode_multi(&ctx); 90 + mipi_dsi_msleep(&ctx, 120); 91 + mipi_dsi_dcs_set_display_on_multi(&ctx); 92 + 93 + return ctx.accum_err; 94 + } 95 + 96 + static int ili9806e_off(struct ili9806e_panel *panel) 97 + { 98 + struct mipi_dsi_multi_context ctx = { .dsi = panel->dsi }; 99 + 100 + mipi_dsi_dcs_set_display_off_multi(&ctx); 101 + mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); 102 + mipi_dsi_msleep(&ctx, 120); 103 + 104 + return ctx.accum_err; 105 + } 106 + 107 + static int ili9806e_prepare(struct drm_panel *panel) 108 + { 109 + struct ili9806e_panel *ctx = to_ili9806e_panel(panel); 110 + int ret; 111 + 112 + ret = ili9806e_power_on(ctx); 113 + if (ret < 0) 114 + return ret; 115 + 116 + ret = ili9806e_on(ctx); 117 + if (ret < 0) { 118 + ili9806e_power_off(ctx); 119 + return ret; 120 + } 121 + 122 + return 0; 123 + } 124 + 125 + static int ili9806e_unprepare(struct drm_panel *panel) 126 + { 127 + struct ili9806e_panel *ctx = to_ili9806e_panel(panel); 128 + struct mipi_dsi_device *dsi = ctx->dsi; 129 + int ret; 130 + 131 + ili9806e_off(ctx); 132 + 133 + ret = ili9806e_power_off(ctx); 134 + if (ret < 0) 135 + dev_err(&dsi->dev, "power off failed: %d\n", ret); 136 + 137 + return ret; 138 + } 139 + 140 + static int ili9806e_get_modes(struct drm_panel *panel, 141 + struct drm_connector *connector) 142 + { 143 + struct ili9806e_panel *ctx = to_ili9806e_panel(panel); 144 + const struct drm_display_mode *mode = ctx->desc->display_mode; 145 + 146 + return drm_connector_helper_get_modes_fixed(connector, mode); 147 + } 148 + 149 + static enum drm_panel_orientation ili9806e_get_orientation(struct drm_panel *panel) 150 + { 151 + struct ili9806e_panel *ctx = to_ili9806e_panel(panel); 152 + 153 + return ctx->orientation; 154 + } 155 + 156 + static const struct drm_panel_funcs ili9806e_funcs = { 157 + .prepare = ili9806e_prepare, 158 + .unprepare = ili9806e_unprepare, 159 + .get_modes = ili9806e_get_modes, 160 + .get_orientation = ili9806e_get_orientation, 161 + }; 162 + 163 + static int ili9806e_dsi_probe(struct mipi_dsi_device *dsi) 164 + { 165 + struct device *dev = &dsi->dev; 166 + struct ili9806e_panel *ctx; 167 + int i, ret; 168 + 169 + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 170 + if (!ctx) 171 + return -ENOMEM; 172 + 173 + ctx->desc = device_get_match_data(dev); 174 + 175 + for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) 176 + ctx->supplies[i].supply = regulator_names[i]; 177 + 178 + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), 179 + ctx->supplies); 180 + if (ret < 0) 181 + return ret; 182 + 183 + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 184 + if (IS_ERR(ctx->reset_gpio)) 185 + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), 186 + "Failed to get reset-gpios\n"); 187 + 188 + mipi_dsi_set_drvdata(dsi, ctx); 189 + ctx->dsi = dsi; 190 + 191 + dsi->mode_flags = ctx->desc->mode_flags; 192 + dsi->format = ctx->desc->format; 193 + dsi->lanes = ctx->desc->lanes; 194 + 195 + drm_panel_init(&ctx->panel, dev, &ili9806e_funcs, 196 + DRM_MODE_CONNECTOR_DSI); 197 + 198 + ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation); 199 + if (ret) 200 + return dev_err_probe(dev, ret, "Failed to get orientation\n"); 201 + 202 + ret = drm_panel_of_backlight(&ctx->panel); 203 + if (ret) 204 + return dev_err_probe(dev, ret, "Failed to get backlight\n"); 205 + 206 + ctx->panel.prepare_prev_first = true; 207 + drm_panel_add(&ctx->panel); 208 + 209 + ret = mipi_dsi_attach(dsi); 210 + if (ret < 0) { 211 + dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); 212 + drm_panel_remove(&ctx->panel); 213 + return ret; 214 + } 215 + 216 + return 0; 217 + } 218 + 219 + static void ili9806e_dsi_remove(struct mipi_dsi_device *dsi) 220 + { 221 + struct ili9806e_panel *ctx = mipi_dsi_get_drvdata(dsi); 222 + 223 + mipi_dsi_detach(dsi); 224 + drm_panel_remove(&ctx->panel); 225 + } 226 + 227 + static void com35h3p70ulc_init(struct mipi_dsi_multi_context *ctx) 228 + { 229 + /* Switch to page 1 */ 230 + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x01); 231 + /* Interface Settings */ 232 + mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x18); 233 + mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x01); 234 + /* Panel Settings */ 235 + mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x03); 236 + mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x00); 237 + mipi_dsi_dcs_write_seq_multi(ctx, 0x60, 0x0d); 238 + mipi_dsi_dcs_write_seq_multi(ctx, 0x61, 0x08); 239 + mipi_dsi_dcs_write_seq_multi(ctx, 0x62, 0x08); 240 + mipi_dsi_dcs_write_seq_multi(ctx, 0x63, 0x09); 241 + /* Power Control */ 242 + mipi_dsi_dcs_write_seq_multi(ctx, 0x40, 0x30); 243 + mipi_dsi_dcs_write_seq_multi(ctx, 0x41, 0x44); 244 + mipi_dsi_dcs_write_seq_multi(ctx, 0x42, 0x00); 245 + mipi_dsi_dcs_write_seq_multi(ctx, 0x43, 0x89); 246 + mipi_dsi_dcs_write_seq_multi(ctx, 0x44, 0x8e); 247 + mipi_dsi_dcs_write_seq_multi(ctx, 0x45, 0xd9); 248 + mipi_dsi_dcs_write_seq_multi(ctx, 0x46, 0x33); 249 + mipi_dsi_dcs_write_seq_multi(ctx, 0x47, 0x33); 250 + mipi_dsi_dcs_write_seq_multi(ctx, 0x50, 0x90); 251 + mipi_dsi_dcs_write_seq_multi(ctx, 0x51, 0x90); 252 + mipi_dsi_dcs_write_seq_multi(ctx, 0x56, 0x00); 253 + /* Gamma Settings */ 254 + mipi_dsi_dcs_write_seq_multi(ctx, 0xa0, 0x00); 255 + mipi_dsi_dcs_write_seq_multi(ctx, 0xa1, 0x0c); 256 + mipi_dsi_dcs_write_seq_multi(ctx, 0xa2, 0x13); 257 + mipi_dsi_dcs_write_seq_multi(ctx, 0xa3, 0x0f); 258 + mipi_dsi_dcs_write_seq_multi(ctx, 0xa4, 0x0a); 259 + mipi_dsi_dcs_write_seq_multi(ctx, 0xa5, 0x0d); 260 + mipi_dsi_dcs_write_seq_multi(ctx, 0xa6, 0x0c); 261 + mipi_dsi_dcs_write_seq_multi(ctx, 0xa7, 0x0b); 262 + mipi_dsi_dcs_write_seq_multi(ctx, 0xa8, 0x01); 263 + mipi_dsi_dcs_write_seq_multi(ctx, 0xa9, 0x06); 264 + mipi_dsi_dcs_write_seq_multi(ctx, 0xaa, 0x15); 265 + mipi_dsi_dcs_write_seq_multi(ctx, 0xab, 0x07); 266 + mipi_dsi_dcs_write_seq_multi(ctx, 0xac, 0x12); 267 + mipi_dsi_dcs_write_seq_multi(ctx, 0xad, 0x28); 268 + mipi_dsi_dcs_write_seq_multi(ctx, 0xae, 0x20); 269 + mipi_dsi_dcs_write_seq_multi(ctx, 0xaf, 0x14); 270 + mipi_dsi_dcs_write_seq_multi(ctx, 0xc0, 0x00); 271 + mipi_dsi_dcs_write_seq_multi(ctx, 0xc1, 0x0c); 272 + mipi_dsi_dcs_write_seq_multi(ctx, 0xc2, 0x13); 273 + mipi_dsi_dcs_write_seq_multi(ctx, 0xc3, 0x0f); 274 + mipi_dsi_dcs_write_seq_multi(ctx, 0xc4, 0x09); 275 + mipi_dsi_dcs_write_seq_multi(ctx, 0xc5, 0x0d); 276 + mipi_dsi_dcs_write_seq_multi(ctx, 0xc6, 0x0c); 277 + mipi_dsi_dcs_write_seq_multi(ctx, 0xc7, 0x0b); 278 + mipi_dsi_dcs_write_seq_multi(ctx, 0xc8, 0x01); 279 + mipi_dsi_dcs_write_seq_multi(ctx, 0xc9, 0x06); 280 + mipi_dsi_dcs_write_seq_multi(ctx, 0xca, 0x14); 281 + mipi_dsi_dcs_write_seq_multi(ctx, 0xcb, 0x07); 282 + mipi_dsi_dcs_write_seq_multi(ctx, 0xcc, 0x0f); 283 + mipi_dsi_dcs_write_seq_multi(ctx, 0xcd, 0x21); 284 + mipi_dsi_dcs_write_seq_multi(ctx, 0xce, 0x17); 285 + mipi_dsi_dcs_write_seq_multi(ctx, 0xcf, 0x0a); 286 + 287 + /* Switch to page 7 */ 288 + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x07); 289 + /* Power Control */ 290 + mipi_dsi_dcs_write_seq_multi(ctx, 0x06, 0x00); 291 + mipi_dsi_dcs_write_seq_multi(ctx, 0x18, 0x1d); 292 + mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x32); 293 + 294 + /* Switch to page 6 */ 295 + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x06); 296 + /* GIP settings */ 297 + mipi_dsi_dcs_write_seq_multi(ctx, 0x00, 0x20); 298 + mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x02); 299 + mipi_dsi_dcs_write_seq_multi(ctx, 0x02, 0x00); 300 + mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x02); 301 + mipi_dsi_dcs_write_seq_multi(ctx, 0x04, 0x01); 302 + mipi_dsi_dcs_write_seq_multi(ctx, 0x05, 0x01); 303 + mipi_dsi_dcs_write_seq_multi(ctx, 0x06, 0x88); 304 + mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x04); 305 + mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x03); 306 + mipi_dsi_dcs_write_seq_multi(ctx, 0x09, 0x80); 307 + mipi_dsi_dcs_write_seq_multi(ctx, 0x0a, 0x00); 308 + mipi_dsi_dcs_write_seq_multi(ctx, 0x0b, 0x00); 309 + mipi_dsi_dcs_write_seq_multi(ctx, 0x0c, 0x01); 310 + mipi_dsi_dcs_write_seq_multi(ctx, 0x0d, 0x01); 311 + mipi_dsi_dcs_write_seq_multi(ctx, 0x0e, 0x00); 312 + mipi_dsi_dcs_write_seq_multi(ctx, 0x0f, 0x00); 313 + mipi_dsi_dcs_write_seq_multi(ctx, 0x10, 0x55); 314 + mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0x50); 315 + mipi_dsi_dcs_write_seq_multi(ctx, 0x12, 0x01); 316 + mipi_dsi_dcs_write_seq_multi(ctx, 0x13, 0x00); 317 + mipi_dsi_dcs_write_seq_multi(ctx, 0x14, 0x00); 318 + mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0x43); 319 + mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0x0b); 320 + mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x00); 321 + mipi_dsi_dcs_write_seq_multi(ctx, 0x18, 0x00); 322 + mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0x10); 323 + mipi_dsi_dcs_write_seq_multi(ctx, 0x1a, 0x00); 324 + mipi_dsi_dcs_write_seq_multi(ctx, 0x1b, 0x00); 325 + mipi_dsi_dcs_write_seq_multi(ctx, 0x1c, 0x00); 326 + mipi_dsi_dcs_write_seq_multi(ctx, 0x1d, 0x00); 327 + mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x01); 328 + mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x23); 329 + mipi_dsi_dcs_write_seq_multi(ctx, 0x22, 0x45); 330 + mipi_dsi_dcs_write_seq_multi(ctx, 0x23, 0x67); 331 + mipi_dsi_dcs_write_seq_multi(ctx, 0x24, 0x01); 332 + mipi_dsi_dcs_write_seq_multi(ctx, 0x25, 0x23); 333 + mipi_dsi_dcs_write_seq_multi(ctx, 0x26, 0x45); 334 + mipi_dsi_dcs_write_seq_multi(ctx, 0x27, 0x67); 335 + mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x02); 336 + mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x22); 337 + mipi_dsi_dcs_write_seq_multi(ctx, 0x32, 0x22); 338 + mipi_dsi_dcs_write_seq_multi(ctx, 0x33, 0x88); 339 + mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0xaa); 340 + mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0xbb); 341 + mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0x66); 342 + mipi_dsi_dcs_write_seq_multi(ctx, 0x37, 0x22); 343 + mipi_dsi_dcs_write_seq_multi(ctx, 0x38, 0x22); 344 + mipi_dsi_dcs_write_seq_multi(ctx, 0x39, 0x22); 345 + mipi_dsi_dcs_write_seq_multi(ctx, 0x3a, 0x22); 346 + mipi_dsi_dcs_write_seq_multi(ctx, 0x3b, 0x22); 347 + mipi_dsi_dcs_write_seq_multi(ctx, 0x3c, 0x22); 348 + mipi_dsi_dcs_write_seq_multi(ctx, 0x3d, 0x22); 349 + mipi_dsi_dcs_write_seq_multi(ctx, 0x3e, 0x22); 350 + mipi_dsi_dcs_write_seq_multi(ctx, 0x3f, 0x22); 351 + mipi_dsi_dcs_write_seq_multi(ctx, 0x40, 0x22); 352 + mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x12); 353 + 354 + /* Switch to page 0 */ 355 + mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x00); 356 + /* Interface Pixel format */ 357 + mipi_dsi_dcs_write_seq_multi(ctx, 0x3a, 0x60); 358 + }; 359 + 360 + static const struct drm_display_mode com35h3p70ulc_default_mode = { 361 + .clock = 22400, 362 + .hdisplay = 480, 363 + .hsync_start = 480 + 16, 364 + .hsync_end = 480 + 16 + 16, 365 + .htotal = 480 + 16 + 16 + 16, 366 + .vdisplay = 640, 367 + .vsync_start = 640 + 52, 368 + .vsync_end = 640 + 52 + 4, 369 + .vtotal = 640 + 52 + 4 + 16, 370 + .width_mm = 53, 371 + .height_mm = 71, 372 + }; 373 + 374 + static const struct panel_desc com35h3p70ulc_desc = { 375 + .init_sequence = com35h3p70ulc_init, 376 + .display_mode = &com35h3p70ulc_default_mode, 377 + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 378 + MIPI_DSI_MODE_LPM, 379 + .format = MIPI_DSI_FMT_RGB888, 380 + .lanes = 2, 381 + }; 382 + 383 + static const struct of_device_id ili9806e_of_match[] = { 384 + { .compatible = "ortustech,com35h3p70ulc", .data = &com35h3p70ulc_desc }, 385 + { } 386 + }; 387 + MODULE_DEVICE_TABLE(of, ili9806e_of_match); 388 + 389 + static struct mipi_dsi_driver ili9806e_dsi_driver = { 390 + .driver = { 391 + .name = "ili9806e-dsi", 392 + .of_match_table = ili9806e_of_match, 393 + }, 394 + .probe = ili9806e_dsi_probe, 395 + .remove = ili9806e_dsi_remove, 396 + }; 397 + module_mipi_dsi_driver(ili9806e_dsi_driver); 398 + 399 + MODULE_AUTHOR("Gunnar Dibbern <gunnar.dibbern@lht.dlh.de>"); 400 + MODULE_AUTHOR("Michael Walle <mwalle@kernel.org>"); 401 + MODULE_DESCRIPTION("Ilitek ILI9806E Controller Driver"); 402 + MODULE_LICENSE("GPL");
+262
drivers/gpu/drm/panel/panel-lincolntech-lcd197.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2024 BayLibre, SAS 4 + * Author: Jerome Brunet <jbrunet@baylibre.com> 5 + */ 6 + 7 + #include <linux/gpio/consumer.h> 8 + #include <linux/module.h> 9 + #include <linux/of.h> 10 + #include <linux/regulator/consumer.h> 11 + 12 + #include <video/mipi_display.h> 13 + 14 + #include <drm/drm_device.h> 15 + #include <drm/drm_probe_helper.h> 16 + #include <drm/drm_mipi_dsi.h> 17 + #include <drm/drm_modes.h> 18 + #include <drm/drm_panel.h> 19 + 20 + struct lincoln_lcd197_panel { 21 + struct drm_panel panel; 22 + struct mipi_dsi_device *dsi; 23 + struct regulator *supply; 24 + struct gpio_desc *enable_gpio; 25 + struct gpio_desc *reset_gpio; 26 + }; 27 + 28 + static inline 29 + struct lincoln_lcd197_panel *to_lincoln_lcd197_panel(struct drm_panel *panel) 30 + { 31 + return container_of(panel, struct lincoln_lcd197_panel, panel); 32 + } 33 + 34 + static int lincoln_lcd197_panel_prepare(struct drm_panel *panel) 35 + { 36 + struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel); 37 + struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi }; 38 + int err; 39 + 40 + gpiod_set_value_cansleep(lcd->enable_gpio, 0); 41 + err = regulator_enable(lcd->supply); 42 + if (err < 0) 43 + return err; 44 + 45 + gpiod_set_value_cansleep(lcd->enable_gpio, 1); 46 + usleep_range(1000, 2000); 47 + gpiod_set_value_cansleep(lcd->reset_gpio, 1); 48 + usleep_range(5000, 6000); 49 + gpiod_set_value_cansleep(lcd->reset_gpio, 0); 50 + msleep(50); 51 + 52 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xff, 0x83, 0x99); 53 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x55); 54 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x02, 0x04, 0x70, 0x90, 0x01, 55 + 0x32, 0x33, 0x11, 0x11, 0x4d, 0x57, 0x56, 0x73, 56 + 0x02, 0x02); 57 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x00, 0x80, 0x80, 0xae, 0x0a, 58 + 0x0e, 0x75, 0x11, 0x00, 0x00, 0x00); 59 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0xff, 0x04, 0xa4, 0x02, 60 + 0xa0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 61 + 0x24, 0x02, 0x04, 0x0a, 0x21, 0x03, 0x00, 0x00, 62 + 0x08, 0xa6, 0x88, 0x04, 0xa4, 0x02, 0xa0, 0x00, 63 + 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x24, 0x02, 64 + 0x04, 0x0a, 0x00, 0x00, 0x08, 0xa6, 0x00, 0x08, 65 + 0x11); 66 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 67 + 0x00, 0x18, 0x18, 0x32, 0x10, 0x09, 0x00, 0x09, 68 + 0x32, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69 + 0x00, 0x00, 0x11, 0x00, 0x02, 0x02, 0x03, 0x00, 70 + 0x00, 0x00, 0x0a, 0x40); 71 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x18, 0x18, 0x18, 0x18, 0x21, 72 + 0x20, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x18, 73 + 0x18, 0x18, 0x18, 0x03, 0x02, 0x01, 0x00, 0x2f, 74 + 0x2f, 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18, 75 + 0x18, 0x18, 0x18); 76 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x18, 0x18, 0x18, 0x18, 0x20, 77 + 0x21, 0x19, 0x19, 0x18, 0x18, 0x19, 0x19, 0x18, 78 + 0x18, 0x18, 0x18, 0x00, 0x01, 0x02, 0x03, 0x2f, 79 + 0x2f, 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18, 80 + 0x18, 0x18, 0x18); 81 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x01); 82 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0a, 0xbe, 0xfa, 0xa0, 0x0a, 83 + 0xbe, 0xfa, 0xa0); 84 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0f, 0xff, 0xff, 0xe0, 0x0f, 85 + 0xff, 0xff, 0xe0); 86 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x02); 87 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0f, 0xff, 0xff, 0xe0, 0x0f, 88 + 0xff, 0xff, 0xe0); 89 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x01, 0x11, 0x1c, 0x17, 0x39, 90 + 0x43, 0x54, 0x51, 0x5a, 0x64, 0x6c, 0x74, 0x7a, 91 + 0x83, 0x8d, 0x92, 0x99, 0xa4, 0xa9, 0xb4, 0xaa, 92 + 0xba, 0xbe, 0x63, 0x5e, 0x69, 0x73, 0x01, 0x11, 93 + 0x1c, 0x17, 0x39, 0x43, 0x54, 0x51, 0x5a, 0x64, 94 + 0x6c, 0x74, 0x7a, 0x83, 0x8d, 0x92, 0x99, 0xa4, 95 + 0xa7, 0xb2, 0xa9, 0xba, 0xbe, 0x63, 0x5e, 0x69, 96 + 0x73); 97 + mipi_dsi_usleep_range(&ctx, 200, 300); 98 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x92, 0x92); 99 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x00); 100 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x40, 0x41, 0x50, 0x49); 101 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xff, 0xf9); 102 + mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x25, 0x5a); 103 + mipi_dsi_dcs_write_seq_multi(&ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x02); 104 + mipi_dsi_dcs_exit_sleep_mode_multi(&ctx); 105 + mipi_dsi_msleep(&ctx, 120); 106 + 107 + if (ctx.accum_err) { 108 + gpiod_set_value_cansleep(lcd->enable_gpio, 0); 109 + gpiod_set_value_cansleep(lcd->reset_gpio, 1); 110 + regulator_disable(lcd->supply); 111 + } 112 + 113 + return ctx.accum_err; 114 + } 115 + 116 + static int lincoln_lcd197_panel_unprepare(struct drm_panel *panel) 117 + { 118 + struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel); 119 + struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi }; 120 + 121 + mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); 122 + mipi_dsi_usleep_range(&ctx, 5000, 6000); 123 + gpiod_set_value_cansleep(lcd->enable_gpio, 0); 124 + gpiod_set_value_cansleep(lcd->reset_gpio, 1); 125 + regulator_disable(lcd->supply); 126 + 127 + return ctx.accum_err; 128 + } 129 + 130 + static int lincoln_lcd197_panel_enable(struct drm_panel *panel) 131 + { 132 + struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel); 133 + struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi }; 134 + 135 + mipi_dsi_dcs_set_display_on_multi(&ctx); 136 + mipi_dsi_msleep(&ctx, 20); 137 + 138 + return ctx.accum_err; 139 + } 140 + 141 + static int lincoln_lcd197_panel_disable(struct drm_panel *panel) 142 + { 143 + struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel); 144 + struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi }; 145 + 146 + mipi_dsi_dcs_set_display_off_multi(&ctx); 147 + mipi_dsi_msleep(&ctx, 50); 148 + 149 + return ctx.accum_err; 150 + } 151 + 152 + static const struct drm_display_mode lcd197_mode = { 153 + .clock = 154002, 154 + .hdisplay = 1080, 155 + .hsync_start = 1080 + 20, 156 + .hsync_end = 1080 + 20 + 6, 157 + .htotal = 1080 + 204, 158 + .vdisplay = 1920, 159 + .vsync_start = 1920 + 4, 160 + .vsync_end = 1920 + 4 + 4, 161 + .vtotal = 1920 + 79, 162 + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 163 + .width_mm = 79, 164 + .height_mm = 125, 165 + .type = DRM_MODE_TYPE_DRIVER, 166 + }; 167 + 168 + static int lincoln_lcd197_panel_get_modes(struct drm_panel *panel, 169 + struct drm_connector *connector) 170 + { 171 + return drm_connector_helper_get_modes_fixed(connector, &lcd197_mode); 172 + } 173 + 174 + static const struct drm_panel_funcs lincoln_lcd197_panel_funcs = { 175 + .prepare = lincoln_lcd197_panel_prepare, 176 + .unprepare = lincoln_lcd197_panel_unprepare, 177 + .enable = lincoln_lcd197_panel_enable, 178 + .disable = lincoln_lcd197_panel_disable, 179 + .get_modes = lincoln_lcd197_panel_get_modes, 180 + }; 181 + 182 + static int lincoln_lcd197_panel_probe(struct mipi_dsi_device *dsi) 183 + { 184 + struct lincoln_lcd197_panel *lcd; 185 + struct device *dev = &dsi->dev; 186 + int err; 187 + 188 + dsi->lanes = 4; 189 + dsi->format = MIPI_DSI_FMT_RGB888; 190 + dsi->mode_flags = (MIPI_DSI_MODE_VIDEO | 191 + MIPI_DSI_MODE_VIDEO_BURST); 192 + 193 + lcd = devm_kzalloc(&dsi->dev, sizeof(*lcd), GFP_KERNEL); 194 + if (!lcd) 195 + return -ENOMEM; 196 + 197 + mipi_dsi_set_drvdata(dsi, lcd); 198 + lcd->dsi = dsi; 199 + 200 + lcd->supply = devm_regulator_get(dev, "power"); 201 + if (IS_ERR(lcd->supply)) 202 + return dev_err_probe(dev, PTR_ERR(lcd->supply), 203 + "failed to get power supply"); 204 + 205 + lcd->enable_gpio = devm_gpiod_get(dev, "enable", 206 + GPIOD_OUT_HIGH); 207 + if (IS_ERR(lcd->enable_gpio)) 208 + return dev_err_probe(dev, PTR_ERR(lcd->enable_gpio), 209 + "failed to get enable gpio"); 210 + 211 + lcd->reset_gpio = devm_gpiod_get(dev, "reset", 212 + GPIOD_OUT_HIGH); 213 + if (IS_ERR(lcd->reset_gpio)) 214 + return dev_err_probe(dev, PTR_ERR(lcd->reset_gpio), 215 + "failed to get reset gpio"); 216 + 217 + drm_panel_init(&lcd->panel, dev, 218 + &lincoln_lcd197_panel_funcs, DRM_MODE_CONNECTOR_DSI); 219 + 220 + err = drm_panel_of_backlight(&lcd->panel); 221 + if (err) 222 + return err; 223 + 224 + drm_panel_add(&lcd->panel); 225 + err = mipi_dsi_attach(dsi); 226 + if (err) 227 + drm_panel_remove(&lcd->panel); 228 + 229 + return err; 230 + } 231 + 232 + static void lincoln_lcd197_panel_remove(struct mipi_dsi_device *dsi) 233 + { 234 + struct lincoln_lcd197_panel *lcd = mipi_dsi_get_drvdata(dsi); 235 + int err; 236 + 237 + err = mipi_dsi_detach(dsi); 238 + if (err < 0) 239 + dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); 240 + 241 + drm_panel_remove(&lcd->panel); 242 + } 243 + 244 + static const struct of_device_id lincoln_lcd197_of_match[] = { 245 + { .compatible = "lincolntech,lcd197", }, 246 + { /* sentinel */ } 247 + }; 248 + MODULE_DEVICE_TABLE(of, lincoln_lcd197_of_match); 249 + 250 + static struct mipi_dsi_driver lincoln_lcd197_panel_driver = { 251 + .driver = { 252 + .name = "panel-lincolntech-lcd197", 253 + .of_match_table = lincoln_lcd197_of_match, 254 + }, 255 + .probe = lincoln_lcd197_panel_probe, 256 + .remove = lincoln_lcd197_panel_remove, 257 + }; 258 + module_mipi_dsi_driver(lincoln_lcd197_panel_driver); 259 + 260 + MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); 261 + MODULE_DESCRIPTION("Lincoln Technologies LCD197 panel driver"); 262 + MODULE_LICENSE("GPL");
+94 -134
drivers/gpu/drm/panel/panel-raydium-rm692e5.c
··· 40 40 usleep_range(10000, 11000); 41 41 } 42 42 43 - static int rm692e5_on(struct rm692e5_panel *ctx) 43 + static void rm692e5_on(struct mipi_dsi_multi_context *dsi_ctx) 44 44 { 45 - struct mipi_dsi_device *dsi = ctx->dsi; 46 - struct device *dev = &dsi->dev; 47 - int ret; 45 + dsi_ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; 48 46 49 - dsi->mode_flags |= MIPI_DSI_MODE_LPM; 47 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x41); 48 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd6, 0x00); 49 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x16); 50 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x8a, 0x87); 51 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x71); 52 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x82, 0x01); 53 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc6, 0x00); 54 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc7, 0x2c); 55 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc8, 0x64); 56 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc9, 0x3c); 57 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xca, 0x80); 58 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xcb, 0x02); 59 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xcc, 0x02); 60 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x38); 61 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0x13); 62 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xf4); 63 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x00, 0xff); 64 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x01, 0xff); 65 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x02, 0xcf); 66 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x03, 0xbc); 67 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x04, 0xb9); 68 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x05, 0x99); 69 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x06, 0x02); 70 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x07, 0x0a); 71 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x08, 0xe0); 72 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x09, 0x4c); 73 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0a, 0xeb); 74 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0b, 0xe8); 75 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0c, 0x32); 76 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0d, 0x07); 77 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xf4); 78 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0d, 0xc0); 79 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0e, 0xff); 80 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0f, 0xff); 81 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x10, 0x33); 82 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x11, 0x6f); 83 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x12, 0x6e); 84 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x13, 0xa6); 85 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x14, 0x80); 86 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x15, 0x02); 87 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x16, 0x38); 88 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x17, 0xd3); 89 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0x3a); 90 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x19, 0xba); 91 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1a, 0xcc); 92 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1b, 0x01); 50 93 51 - mipi_dsi_generic_write_seq(dsi, 0xfe, 0x41); 52 - mipi_dsi_generic_write_seq(dsi, 0xd6, 0x00); 53 - mipi_dsi_generic_write_seq(dsi, 0xfe, 0x16); 54 - mipi_dsi_generic_write_seq(dsi, 0x8a, 0x87); 55 - mipi_dsi_generic_write_seq(dsi, 0xfe, 0x71); 56 - mipi_dsi_generic_write_seq(dsi, 0x82, 0x01); 57 - mipi_dsi_generic_write_seq(dsi, 0xc6, 0x00); 58 - mipi_dsi_generic_write_seq(dsi, 0xc7, 0x2c); 59 - mipi_dsi_generic_write_seq(dsi, 0xc8, 0x64); 60 - mipi_dsi_generic_write_seq(dsi, 0xc9, 0x3c); 61 - mipi_dsi_generic_write_seq(dsi, 0xca, 0x80); 62 - mipi_dsi_generic_write_seq(dsi, 0xcb, 0x02); 63 - mipi_dsi_generic_write_seq(dsi, 0xcc, 0x02); 64 - mipi_dsi_generic_write_seq(dsi, 0xfe, 0x38); 65 - mipi_dsi_generic_write_seq(dsi, 0x18, 0x13); 66 - mipi_dsi_generic_write_seq(dsi, 0xfe, 0xf4); 67 - mipi_dsi_generic_write_seq(dsi, 0x00, 0xff); 68 - mipi_dsi_generic_write_seq(dsi, 0x01, 0xff); 69 - mipi_dsi_generic_write_seq(dsi, 0x02, 0xcf); 70 - mipi_dsi_generic_write_seq(dsi, 0x03, 0xbc); 71 - mipi_dsi_generic_write_seq(dsi, 0x04, 0xb9); 72 - mipi_dsi_generic_write_seq(dsi, 0x05, 0x99); 73 - mipi_dsi_generic_write_seq(dsi, 0x06, 0x02); 74 - mipi_dsi_generic_write_seq(dsi, 0x07, 0x0a); 75 - mipi_dsi_generic_write_seq(dsi, 0x08, 0xe0); 76 - mipi_dsi_generic_write_seq(dsi, 0x09, 0x4c); 77 - mipi_dsi_generic_write_seq(dsi, 0x0a, 0xeb); 78 - mipi_dsi_generic_write_seq(dsi, 0x0b, 0xe8); 79 - mipi_dsi_generic_write_seq(dsi, 0x0c, 0x32); 80 - mipi_dsi_generic_write_seq(dsi, 0x0d, 0x07); 81 - mipi_dsi_generic_write_seq(dsi, 0xfe, 0xf4); 82 - mipi_dsi_generic_write_seq(dsi, 0x0d, 0xc0); 83 - mipi_dsi_generic_write_seq(dsi, 0x0e, 0xff); 84 - mipi_dsi_generic_write_seq(dsi, 0x0f, 0xff); 85 - mipi_dsi_generic_write_seq(dsi, 0x10, 0x33); 86 - mipi_dsi_generic_write_seq(dsi, 0x11, 0x6f); 87 - mipi_dsi_generic_write_seq(dsi, 0x12, 0x6e); 88 - mipi_dsi_generic_write_seq(dsi, 0x13, 0xa6); 89 - mipi_dsi_generic_write_seq(dsi, 0x14, 0x80); 90 - mipi_dsi_generic_write_seq(dsi, 0x15, 0x02); 91 - mipi_dsi_generic_write_seq(dsi, 0x16, 0x38); 92 - mipi_dsi_generic_write_seq(dsi, 0x17, 0xd3); 93 - mipi_dsi_generic_write_seq(dsi, 0x18, 0x3a); 94 - mipi_dsi_generic_write_seq(dsi, 0x19, 0xba); 95 - mipi_dsi_generic_write_seq(dsi, 0x1a, 0xcc); 96 - mipi_dsi_generic_write_seq(dsi, 0x1b, 0x01); 94 + mipi_dsi_dcs_nop_multi(dsi_ctx); 97 95 98 - ret = mipi_dsi_dcs_nop(dsi); 99 - if (ret < 0) { 100 - dev_err(dev, "Failed to nop: %d\n", ret); 101 - return ret; 102 - } 103 - msleep(32); 96 + mipi_dsi_msleep(dsi_ctx, 32); 104 97 105 - mipi_dsi_generic_write_seq(dsi, 0xfe, 0x38); 106 - mipi_dsi_generic_write_seq(dsi, 0x18, 0x13); 107 - mipi_dsi_generic_write_seq(dsi, 0xfe, 0xd1); 108 - mipi_dsi_generic_write_seq(dsi, 0xd3, 0x00); 109 - mipi_dsi_generic_write_seq(dsi, 0xd0, 0x00); 110 - mipi_dsi_generic_write_seq(dsi, 0xd2, 0x00); 111 - mipi_dsi_generic_write_seq(dsi, 0xd4, 0x00); 112 - mipi_dsi_generic_write_seq(dsi, 0xb4, 0x01); 113 - mipi_dsi_generic_write_seq(dsi, 0xfe, 0xf9); 114 - mipi_dsi_generic_write_seq(dsi, 0x00, 0xaf); 115 - mipi_dsi_generic_write_seq(dsi, 0x1d, 0x37); 116 - mipi_dsi_generic_write_seq(dsi, 0x44, 0x0a, 0x7b); 117 - mipi_dsi_generic_write_seq(dsi, 0xfe, 0x00); 118 - mipi_dsi_generic_write_seq(dsi, 0xfa, 0x01); 119 - mipi_dsi_generic_write_seq(dsi, 0xc2, 0x08); 120 - mipi_dsi_generic_write_seq(dsi, 0x35, 0x00); 121 - mipi_dsi_generic_write_seq(dsi, 0x51, 0x05, 0x42); 98 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x38); 99 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0x13); 100 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xd1); 101 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd3, 0x00); 102 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd0, 0x00); 103 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd2, 0x00); 104 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd4, 0x00); 105 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xb4, 0x01); 106 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xf9); 107 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x00, 0xaf); 108 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1d, 0x37); 109 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x44, 0x0a, 0x7b); 110 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x00); 111 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfa, 0x01); 112 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc2, 0x08); 113 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x35, 0x00); 114 + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x51, 0x05, 0x42); 122 115 123 - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 124 - if (ret < 0) { 125 - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); 126 - return ret; 127 - } 128 - msleep(100); 129 - 130 - ret = mipi_dsi_dcs_set_display_on(dsi); 131 - if (ret < 0) { 132 - dev_err(dev, "Failed to set display on: %d\n", ret); 133 - return ret; 134 - } 135 - 136 - return 0; 116 + mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx); 117 + mipi_dsi_msleep(dsi_ctx, 100); 118 + mipi_dsi_dcs_set_display_on_multi(dsi_ctx); 137 119 } 138 120 139 121 static int rm692e5_disable(struct drm_panel *panel) 140 122 { 141 123 struct rm692e5_panel *ctx = to_rm692e5_panel(panel); 142 124 struct mipi_dsi_device *dsi = ctx->dsi; 143 - struct device *dev = &dsi->dev; 144 - int ret; 125 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; 145 126 146 127 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 147 128 148 - mipi_dsi_generic_write_seq(dsi, 0xfe, 0x00); 129 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xfe, 0x00); 149 130 150 - ret = mipi_dsi_dcs_set_display_off(dsi); 151 - if (ret < 0) { 152 - dev_err(dev, "Failed to set display off: %d\n", ret); 153 - return ret; 154 - } 131 + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); 155 132 156 - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 157 - if (ret < 0) { 158 - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); 159 - return ret; 160 - } 161 - msleep(100); 133 + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); 162 134 163 - return 0; 135 + mipi_dsi_msleep(&dsi_ctx, 100); 136 + 137 + return dsi_ctx.accum_err; 164 138 } 165 139 166 140 static int rm692e5_prepare(struct drm_panel *panel) 167 141 { 168 142 struct rm692e5_panel *ctx = to_rm692e5_panel(panel); 169 143 struct drm_dsc_picture_parameter_set pps; 170 - struct device *dev = &ctx->dsi->dev; 171 - int ret; 144 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; 172 145 173 - ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 174 - if (ret < 0) { 175 - dev_err(dev, "Failed to enable regulators: %d\n", ret); 176 - return ret; 177 - } 146 + dsi_ctx.accum_err = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 147 + if (dsi_ctx.accum_err) 148 + return dsi_ctx.accum_err; 178 149 179 150 rm692e5_reset(ctx); 180 151 181 - ret = rm692e5_on(ctx); 182 - if (ret < 0) { 183 - dev_err(dev, "Failed to initialize panel: %d\n", ret); 184 - gpiod_set_value_cansleep(ctx->reset_gpio, 1); 185 - regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 186 - return ret; 187 - } 152 + rm692e5_on(&dsi_ctx); 188 153 189 154 drm_dsc_pps_payload_pack(&pps, &ctx->dsc); 190 155 191 - ret = mipi_dsi_picture_parameter_set(ctx->dsi, &pps); 192 - if (ret < 0) { 193 - dev_err(panel->dev, "failed to transmit PPS: %d\n", ret); 194 - return ret; 195 - } 156 + mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps); 157 + mipi_dsi_compression_mode_ext_multi(&dsi_ctx, true, MIPI_DSI_COMPRESSION_DSC, 0); 158 + mipi_dsi_msleep(&dsi_ctx, 28); 196 159 197 - ret = mipi_dsi_compression_mode(ctx->dsi, true); 198 - if (ret < 0) { 199 - dev_err(dev, "failed to enable compression mode: %d\n", ret); 200 - return ret; 201 - } 202 - 203 - msleep(28); 204 - 205 - mipi_dsi_generic_write_seq(ctx->dsi, 0xfe, 0x40); 160 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xfe, 0x40); 206 161 207 162 /* 0x05 -> 90Hz, 0x00 -> 60Hz */ 208 - mipi_dsi_generic_write_seq(ctx->dsi, 0xbd, 0x05); 163 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x05); 209 164 210 - mipi_dsi_generic_write_seq(ctx->dsi, 0xfe, 0x00); 165 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xfe, 0x00); 211 166 212 - return 0; 167 + if (dsi_ctx.accum_err) { 168 + gpiod_set_value_cansleep(ctx->reset_gpio, 1); 169 + regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 170 + } 171 + 172 + return dsi_ctx.accum_err; 213 173 } 214 174 215 175 static int rm692e5_unprepare(struct drm_panel *panel)
+392 -428
drivers/gpu/drm/panel/panel-sitronix-st7703.c
··· 69 69 unsigned int lanes; 70 70 unsigned long mode_flags; 71 71 enum mipi_dsi_pixel_format format; 72 - int (*init_sequence)(struct st7703 *ctx); 72 + void (*init_sequence)(struct mipi_dsi_multi_context *dsi_ctx); 73 73 }; 74 74 75 75 static inline struct st7703 *panel_to_st7703(struct drm_panel *panel) ··· 77 77 return container_of(panel, struct st7703, panel); 78 78 } 79 79 80 - static int jh057n_init_sequence(struct st7703 *ctx) 80 + static void jh057n_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 81 81 { 82 - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 83 - 84 82 /* 85 83 * Init sequence was supplied by the panel vendor. Most of the commands 86 84 * resemble the ST7703 but the number of parameters often don't match 87 85 * so it's likely a clone. 88 86 */ 89 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC, 90 - 0xF1, 0x12, 0x83); 91 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF, 92 - 0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00, 93 - 0x00, 0x00); 94 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR, 95 - 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70, 96 - 0x00); 97 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E); 98 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B); 99 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); 100 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30); 101 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ, 102 - 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00, 103 - 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10); 104 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08); 105 - msleep(20); 87 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 88 + 0xF1, 0x12, 0x83); 89 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 90 + 0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00, 91 + 0x00, 0x00); 92 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 93 + 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70, 94 + 0x00); 95 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x4E); 96 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0B); 97 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 98 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30); 99 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 100 + 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00, 101 + 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10); 102 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x08, 0x08); 103 + mipi_dsi_msleep(dsi_ctx, 20); 106 104 107 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F); 108 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 109 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1, 110 - 0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12, 111 - 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, 112 - 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 113 - 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88, 114 - 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64, 115 - 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 116 - 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 117 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 118 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2, 119 - 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 120 - 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88, 121 - 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13, 122 - 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 123 - 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00, 124 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 125 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A, 126 - 0xA5, 0x00, 0x00, 0x00, 0x00); 127 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA, 128 - 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37, 129 - 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11, 130 - 0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 131 - 0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 132 - 0x11, 0x18); 133 - msleep(20); 134 - 135 - return 0; 105 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x3F, 0x3F); 106 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 107 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 108 + 0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12, 109 + 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, 110 + 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 111 + 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88, 112 + 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64, 113 + 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 114 + 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 115 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 116 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 117 + 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 118 + 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88, 119 + 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13, 120 + 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 121 + 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00, 122 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 123 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A, 124 + 0xA5, 0x00, 0x00, 0x00, 0x00); 125 + mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 126 + 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37, 127 + 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11, 128 + 0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 129 + 0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 130 + 0x11, 0x18); 131 + mipi_dsi_msleep(dsi_ctx, 20); 136 132 } 137 133 138 134 static const struct drm_display_mode jh057n00900_mode = { ··· 155 159 .init_sequence = jh057n_init_sequence, 156 160 }; 157 161 158 - static int xbd599_init_sequence(struct st7703 *ctx) 162 + static void xbd599_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 159 163 { 160 - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 161 - 162 164 /* 163 165 * Init sequence was supplied by the panel vendor. 164 166 */ 165 167 166 168 /* Magic sequence to unlock user commands below. */ 167 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83); 169 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83); 168 170 169 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 170 - 0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */ 171 - 0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */ 172 - 0x05, /* IHSRX = x6 (Low High Speed driving ability) */ 173 - 0xF9, /* TX_CLK_SEL = fDSICLK/16 */ 174 - 0x0E, /* HFP_OSC (min. HFP number in DSI mode) */ 175 - 0x0E, /* HBP_OSC (min. HBP number in DSI mode) */ 176 - /* The rest is undocumented in ST7703 datasheet */ 177 - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 178 - 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 179 - 0x4F, 0x11, 0x00, 0x00, 0x37); 171 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 172 + 0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */ 173 + 0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */ 174 + 0x05, /* IHSRX = x6 (Low High Speed driving ability) */ 175 + 0xF9, /* TX_CLK_SEL = fDSICLK/16 */ 176 + 0x0E, /* HFP_OSC (min. HFP number in DSI mode) */ 177 + 0x0E, /* HBP_OSC (min. HBP number in DSI mode) */ 178 + /* The rest is undocumented in ST7703 datasheet */ 179 + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 180 + 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02, 181 + 0x4F, 0x11, 0x00, 0x00, 0x37); 180 182 181 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 182 - 0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */ 183 - 0x22, /* DT = 15ms XDK_ECP = x2 */ 184 - 0x20, /* PFM_DC_DIV = /1 */ 185 - 0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */); 183 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 184 + 0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */ 185 + 0x22, /* DT = 15ms XDK_ECP = x2 */ 186 + 0x20, /* PFM_DC_DIV = /1 */ 187 + 0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */); 186 188 187 189 /* RGB I/F porch timing */ 188 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 189 - 0x10, /* VBP_RGB_GEN */ 190 - 0x10, /* VFP_RGB_GEN */ 191 - 0x05, /* DE_BP_RGB_GEN */ 192 - 0x05, /* DE_FP_RGB_GEN */ 193 - /* The rest is undocumented in ST7703 datasheet */ 194 - 0x03, 0xFF, 195 - 0x00, 0x00, 196 - 0x00, 0x00); 190 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 191 + 0x10, /* VBP_RGB_GEN */ 192 + 0x10, /* VFP_RGB_GEN */ 193 + 0x05, /* DE_BP_RGB_GEN */ 194 + 0x05, /* DE_FP_RGB_GEN */ 195 + /* The rest is undocumented in ST7703 datasheet */ 196 + 0x03, 0xFF, 197 + 0x00, 0x00, 198 + 0x00, 0x00); 197 199 198 200 /* Source driving settings. */ 199 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 200 - 0x73, /* N_POPON */ 201 - 0x73, /* N_NOPON */ 202 - 0x50, /* I_POPON */ 203 - 0x50, /* I_NOPON */ 204 - 0x00, /* SCR[31,24] */ 205 - 0xC0, /* SCR[23,16] */ 206 - 0x08, /* SCR[15,8] */ 207 - 0x70, /* SCR[7,0] */ 208 - 0x00 /* Undocumented */); 201 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 202 + 0x73, /* N_POPON */ 203 + 0x73, /* N_NOPON */ 204 + 0x50, /* I_POPON */ 205 + 0x50, /* I_NOPON */ 206 + 0x00, /* SCR[31,24] */ 207 + 0xC0, /* SCR[23,16] */ 208 + 0x08, /* SCR[15,8] */ 209 + 0x70, /* SCR[7,0] */ 210 + 0x00 /* Undocumented */); 209 211 210 212 /* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */ 211 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E); 213 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x4E); 212 214 213 215 /* 214 216 * SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan) 215 217 * REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR) 216 218 */ 217 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B); 219 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0B); 218 220 219 221 /* Zig-Zag Type C column inversion. */ 220 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); 222 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 221 223 222 224 /* Set display resolution. */ 223 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 224 - 0xF0, /* NL = 240 */ 225 - 0x12, /* RES_V_LSB = 0, BLK_CON = VSSD, 226 - * RESO_SEL = 720RGB 227 - */ 228 - 0xF0 /* WHITE_GND_EN = 1 (GND), 229 - * WHITE_FRAME_SEL = 7 frames, 230 - * ISC = 0 frames 231 - */); 225 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 226 + 0xF0, /* NL = 240 */ 227 + 0x12, /* RES_V_LSB = 0, BLK_CON = VSSD, 228 + * RESO_SEL = 720RGB 229 + */ 230 + 0xF0 /* WHITE_GND_EN = 1 (GND), 231 + * WHITE_FRAME_SEL = 7 frames, 232 + * ISC = 0 frames 233 + */); 232 234 233 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 234 - 0x00, /* PNOEQ */ 235 - 0x00, /* NNOEQ */ 236 - 0x0B, /* PEQGND */ 237 - 0x0B, /* NEQGND */ 238 - 0x10, /* PEQVCI */ 239 - 0x10, /* NEQVCI */ 240 - 0x00, /* PEQVCI1 */ 241 - 0x00, /* NEQVCI1 */ 242 - 0x00, /* reserved */ 243 - 0x00, /* reserved */ 244 - 0xFF, /* reserved */ 245 - 0x00, /* reserved */ 246 - 0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */ 247 - 0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in) 248 - * VEDIO_NO_CHECK_EN = 0 249 - * ESD_WHITE_GND_EN = 0 250 - * ESD_DET_TIME_SEL = 0 frames 251 - */); 235 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 236 + 0x00, /* PNOEQ */ 237 + 0x00, /* NNOEQ */ 238 + 0x0B, /* PEQGND */ 239 + 0x0B, /* NEQGND */ 240 + 0x10, /* PEQVCI */ 241 + 0x10, /* NEQVCI */ 242 + 0x00, /* PEQVCI1 */ 243 + 0x00, /* NEQVCI1 */ 244 + 0x00, /* reserved */ 245 + 0x00, /* reserved */ 246 + 0xFF, /* reserved */ 247 + 0x00, /* reserved */ 248 + 0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */ 249 + 0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in) 250 + * VEDIO_NO_CHECK_EN = 0 251 + * ESD_WHITE_GND_EN = 0 252 + * ESD_DET_TIME_SEL = 0 frames 253 + */); 252 254 253 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x01, 0x00, 0xFF, 0xFF, 0x00); 255 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x01, 0x00, 0xFF, 0xFF, 0x00); 254 256 255 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 256 - 0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */ 257 - 0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */ 258 - 0x32, /* VRP */ 259 - 0x32, /* VRN */ 260 - 0x77, /* reserved */ 261 - 0xF1, /* APS = 1 (small), 262 - * VGL_DET_EN = 1, VGH_DET_EN = 1, 263 - * VGL_TURBO = 1, VGH_TURBO = 1 264 - */ 265 - 0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */ 266 - 0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */ 267 - 0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */ 268 - 0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */ 269 - 0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */ 270 - 0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */); 257 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 258 + 0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */ 259 + 0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */ 260 + 0x32, /* VRP */ 261 + 0x32, /* VRN */ 262 + 0x77, /* reserved */ 263 + 0xF1, /* APS = 1 (small), 264 + * VGL_DET_EN = 1, VGH_DET_EN = 1, 265 + * VGL_TURBO = 1, VGH_TURBO = 1 266 + */ 267 + 0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */ 268 + 0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */ 269 + 0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */ 270 + 0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */ 271 + 0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */ 272 + 0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */); 271 273 272 274 /* Reference voltage. */ 273 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 274 - 0x07, /* VREF_SEL = 4.2V */ 275 - 0x07 /* NVREF_SEL = 4.2V */); 275 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 276 + 0x07, /* VREF_SEL = 4.2V */ 277 + 0x07 /* NVREF_SEL = 4.2V */); 276 278 277 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 278 - 0x2C, /* VCOMDC_F = -0.67V */ 279 - 0x2C /* VCOMDC_B = -0.67V */); 279 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 280 + 0x2C, /* VCOMDC_F = -0.67V */ 281 + 0x2C /* VCOMDC_B = -0.67V */); 280 282 281 283 /* Undocumented command. */ 282 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 284 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 283 285 284 286 /* This command is to set forward GIP timing. */ 285 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 286 - 0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12, 287 - 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, 288 - 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 289 - 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88, 290 - 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64, 291 - 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 292 - 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 293 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 287 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 288 + 0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12, 289 + 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, 290 + 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 291 + 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88, 292 + 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64, 293 + 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 294 + 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 295 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 294 296 295 297 /* This command is to set backward GIP timing. */ 296 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 297 - 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 298 - 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88, 299 - 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13, 300 - 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 301 - 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00, 302 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 303 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A, 304 - 0xA5, 0x00, 0x00, 0x00, 0x00); 298 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 299 + 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 300 + 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88, 301 + 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13, 302 + 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 303 + 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00, 304 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 305 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A, 306 + 0xA5, 0x00, 0x00, 0x00, 0x00); 305 307 306 308 /* Adjust the gamma characteristics of the panel. */ 307 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 308 - 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35, 309 - 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12, 310 - 0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 311 - 0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 312 - 0x12, 0x18); 313 - 314 - return 0; 309 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 310 + 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35, 311 + 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12, 312 + 0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 313 + 0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 314 + 0x12, 0x18); 315 315 } 316 316 317 317 static const struct drm_display_mode xbd599_mode = { ··· 333 341 .init_sequence = xbd599_init_sequence, 334 342 }; 335 343 336 - static int rg353v2_init_sequence(struct st7703 *ctx) 344 + static void rg353v2_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 337 345 { 338 - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 339 - 340 346 /* 341 347 * Init sequence was supplied by the panel vendor. 342 348 */ 343 349 344 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 345 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 346 - 0xda, 0x80); 347 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x00, 0x13, 0x70); 348 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28, 349 - 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 350 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); 351 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x0a, 0x0a); 352 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x92, 0x92); 353 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 354 - 0xf0, 0x63); 355 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 356 - 0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 357 - 0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 358 - 0x00, 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37); 359 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x47); 360 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 361 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 362 - 0x00, 0x00, 0x12, 0x50, 0x00); 363 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x53, 0xc0, 0x32, 364 - 0x32, 0x77, 0xe1, 0xdd, 0xdd, 0x77, 0x77, 0x33, 365 - 0x33); 366 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff, 367 - 0x00, 0xff); 368 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00, 369 - 0x00, 0x00); 370 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e, 371 - 0x02); 372 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b); 373 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0d, 374 - 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 0x0d, 375 - 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a, 0x00, 0x07, 376 - 0x0d, 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 377 - 0x0d, 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a); 378 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, 379 - 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 380 - 0xc0, 0x10); 381 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x02, 0x00, 382 - 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x80, 383 - 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00, 384 - 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 385 - 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88, 386 - 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35, 387 - 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 388 - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 389 - 0x00, 0x00, 0x00); 390 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02, 391 - 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 392 - 0x81, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88, 393 - 0x88, 0x88, 0x88, 0x80, 0x88, 0xba, 0x06, 0x42, 394 - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00, 395 - 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 396 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 397 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 398 - 0x00); 399 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01); 400 - 401 - return 0; 350 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 351 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 352 + 0xda, 0x80); 353 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x00, 0x13, 0x70); 354 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28, 355 + 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 356 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 357 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x0a, 0x0a); 358 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x92, 0x92); 359 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 360 + 0xf0, 0x63); 361 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 362 + 0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 363 + 0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 364 + 0x00, 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37); 365 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x47); 366 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 367 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 368 + 0x00, 0x00, 0x12, 0x50, 0x00); 369 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x53, 0xc0, 0x32, 370 + 0x32, 0x77, 0xe1, 0xdd, 0xdd, 0x77, 0x77, 0x33, 371 + 0x33); 372 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff, 373 + 0x00, 0xff); 374 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00, 375 + 0x00, 0x00); 376 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e, 377 + 0x02); 378 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b); 379 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0d, 380 + 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 0x0d, 381 + 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a, 0x00, 0x07, 382 + 0x0d, 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 383 + 0x0d, 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a); 384 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, 385 + 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 386 + 0xc0, 0x10); 387 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x02, 0x00, 388 + 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x80, 389 + 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00, 390 + 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 391 + 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88, 392 + 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35, 393 + 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 394 + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 395 + 0x00, 0x00, 0x00); 396 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02, 397 + 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 398 + 0x81, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88, 399 + 0x88, 0x88, 0x88, 0x80, 0x88, 0xba, 0x06, 0x42, 400 + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00, 401 + 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 402 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 403 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 404 + 0x00); 405 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01); 402 406 } 403 407 404 408 static const struct drm_display_mode rg353v2_mode = { ··· 421 433 .init_sequence = rg353v2_init_sequence, 422 434 }; 423 435 424 - static int rgb30panel_init_sequence(struct st7703 *ctx) 436 + static void rgb30panel_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 425 437 { 426 - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 427 - 428 438 /* Init sequence extracted from Powkiddy RGB30 BSP kernel. */ 429 439 430 440 /* 431 441 * For some reason this specific panel must be taken out of sleep 432 442 * before the full init sequence, or else it will not display. 433 443 */ 434 - mipi_dsi_dcs_exit_sleep_mode(dsi); 435 - msleep(250); 444 + mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx); 445 + mipi_dsi_msleep(dsi_ctx, 250); 436 446 437 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 438 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9, 439 - 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 440 - 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00, 441 - 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37); 442 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0, 443 - 0x63); 444 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 445 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28, 446 - 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 447 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 448 - 0x00, 0x00, 0x12, 0x70, 0x00); 449 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x46); 450 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b); 451 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); 452 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x3c, 0x12, 0x30); 453 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, 454 - 0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 455 - 0xc0, 0x10); 456 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x36, 0x00, 0x32, 457 - 0x32, 0x77, 0xf1, 0xcc, 0xcc, 0x77, 0x77, 0x33, 458 - 0x33); 459 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x0a, 0x0a); 460 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x88, 0x88); 461 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x0a, 0x10, 462 - 0x0f, 0xa1, 0x80, 0x12, 0x31, 0x23, 0x47, 0x86, 463 - 0xa1, 0x80, 0x47, 0x08, 0x00, 0x00, 0x0d, 0x00, 464 - 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 465 - 0x48, 0x02, 0x8b, 0xaf, 0x46, 0x02, 0x88, 0x88, 466 - 0x88, 0x88, 0x88, 0x48, 0x13, 0x8b, 0xaf, 0x57, 467 - 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 468 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 469 - 0x00, 0x00, 0x00); 470 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x96, 0x12, 0x01, 0x01, 471 - 0x01, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 472 - 0x4f, 0x31, 0x8b, 0xa8, 0x31, 0x75, 0x88, 0x88, 473 - 0x88, 0x88, 0x88, 0x4f, 0x20, 0x8b, 0xa8, 0x20, 474 - 0x64, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00, 475 - 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 476 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 477 - 0x00, 0x00, 0x40, 0xa1, 0x80, 0x00, 0x00, 0x00, 478 - 0x00); 479 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x0a, 0x0f, 480 - 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d, 0x10, 481 - 0x13, 0x15, 0x14, 0x15, 0x10, 0x17, 0x00, 0x0a, 482 - 0x0f, 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d, 483 - 0x10, 0x13, 0x15, 0x14, 0x15, 0x10, 0x17); 484 - 485 - return 0; 447 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 448 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9, 449 + 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 450 + 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00, 451 + 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37); 452 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0, 453 + 0x63); 454 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 455 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28, 456 + 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 457 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 458 + 0x00, 0x00, 0x12, 0x70, 0x00); 459 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x46); 460 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b); 461 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 462 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x3c, 0x12, 0x30); 463 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, 464 + 0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 465 + 0xc0, 0x10); 466 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x36, 0x00, 0x32, 467 + 0x32, 0x77, 0xf1, 0xcc, 0xcc, 0x77, 0x77, 0x33, 468 + 0x33); 469 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x0a, 0x0a); 470 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x88, 0x88); 471 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x0a, 0x10, 472 + 0x0f, 0xa1, 0x80, 0x12, 0x31, 0x23, 0x47, 0x86, 473 + 0xa1, 0x80, 0x47, 0x08, 0x00, 0x00, 0x0d, 0x00, 474 + 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 475 + 0x48, 0x02, 0x8b, 0xaf, 0x46, 0x02, 0x88, 0x88, 476 + 0x88, 0x88, 0x88, 0x48, 0x13, 0x8b, 0xaf, 0x57, 477 + 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 478 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 479 + 0x00, 0x00, 0x00); 480 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x96, 0x12, 0x01, 0x01, 481 + 0x01, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 482 + 0x4f, 0x31, 0x8b, 0xa8, 0x31, 0x75, 0x88, 0x88, 483 + 0x88, 0x88, 0x88, 0x4f, 0x20, 0x8b, 0xa8, 0x20, 484 + 0x64, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00, 485 + 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 486 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 487 + 0x00, 0x00, 0x40, 0xa1, 0x80, 0x00, 0x00, 0x00, 488 + 0x00); 489 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x0a, 0x0f, 490 + 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d, 0x10, 491 + 0x13, 0x15, 0x14, 0x15, 0x10, 0x17, 0x00, 0x0a, 492 + 0x0f, 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d, 493 + 0x10, 0x13, 0x15, 0x14, 0x15, 0x10, 0x17); 486 494 } 487 495 488 496 static const struct drm_display_mode rgb30panel_mode = { ··· 505 521 .init_sequence = rgb30panel_init_sequence, 506 522 }; 507 523 508 - static int rgb10max3_panel_init_sequence(struct st7703 *ctx) 524 + static void rgb10max3_panel_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 509 525 { 510 - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 511 - 512 526 /* Init sequence extracted from Powkiddy RGB10MAX3 BSP kernel. */ 513 527 514 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 515 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 0xda, 516 - 0x80); 517 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0xc8, 0x02, 0x30); 518 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28, 519 - 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 520 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); 521 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x04, 0x04); 522 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x78, 0x78); 523 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0, 524 - 0x63); 525 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9, 526 - 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 527 - 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00, 528 - 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37); 529 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x47); 530 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 531 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 532 - 0x00, 0x00, 0x12, 0x70, 0x00); 533 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x25, 0x00, 0x32, 534 - 0x32, 0x77, 0xe1, 0xff, 0xff, 0xcc, 0xcc, 0x77, 535 - 0x77); 536 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff, 537 - 0x00, 0xff); 538 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00, 539 - 0x00, 0x00); 540 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e, 541 - 0x02); 542 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b); 543 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x04, 0x07, 544 - 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b, 0x0e, 545 - 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17, 0x00, 0x04, 546 - 0x07, 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b, 547 - 0x0e, 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17); 548 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x03, 0x03, 0x03, 0x03, 549 - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 550 - 0xc0, 0x10); 551 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x08, 0x00, 552 - 0x00, 0x41, 0xf8, 0x12, 0x31, 0x23, 0x37, 0x86, 553 - 0x11, 0xc8, 0x37, 0x2a, 0x00, 0x00, 0x0c, 0x00, 554 - 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 555 - 0x88, 0x20, 0x46, 0x02, 0x88, 0x88, 0x88, 0x88, 556 - 0x88, 0x88, 0xff, 0x88, 0x31, 0x57, 0x13, 0x88, 557 - 0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0x00, 0x00, 558 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 559 - 0x00, 0x00, 0x00); 560 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x00, 0x1a, 0x00, 0x00, 561 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 562 - 0x8f, 0x13, 0x31, 0x75, 0x88, 0x88, 0x88, 0x88, 563 - 0x88, 0x88, 0xf8, 0x8f, 0x02, 0x20, 0x64, 0x88, 564 - 0x88, 0x88, 0x88, 0x88, 0x88, 0xf8, 0x00, 0x00, 565 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 566 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 567 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 568 - 0x00); 569 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01); 570 - 571 - return 0; 528 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 529 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 0xda, 530 + 0x80); 531 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0xc8, 0x02, 0x30); 532 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28, 533 + 0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 534 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 535 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x04, 0x04); 536 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x78, 0x78); 537 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0, 538 + 0x63); 539 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9, 540 + 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 541 + 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00, 542 + 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37); 543 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x47); 544 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 545 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 546 + 0x00, 0x00, 0x12, 0x70, 0x00); 547 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x25, 0x00, 0x32, 548 + 0x32, 0x77, 0xe1, 0xff, 0xff, 0xcc, 0xcc, 0x77, 549 + 0x77); 550 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff, 551 + 0x00, 0xff); 552 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00, 553 + 0x00, 0x00); 554 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e, 555 + 0x02); 556 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b); 557 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x04, 0x07, 558 + 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b, 0x0e, 559 + 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17, 0x00, 0x04, 560 + 0x07, 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b, 561 + 0x0e, 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17); 562 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x03, 0x03, 0x03, 0x03, 563 + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 564 + 0xc0, 0x10); 565 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x08, 0x00, 566 + 0x00, 0x41, 0xf8, 0x12, 0x31, 0x23, 0x37, 0x86, 567 + 0x11, 0xc8, 0x37, 0x2a, 0x00, 0x00, 0x0c, 0x00, 568 + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 569 + 0x88, 0x20, 0x46, 0x02, 0x88, 0x88, 0x88, 0x88, 570 + 0x88, 0x88, 0xff, 0x88, 0x31, 0x57, 0x13, 0x88, 571 + 0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0x00, 0x00, 572 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 573 + 0x00, 0x00, 0x00); 574 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x00, 0x1a, 0x00, 0x00, 575 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 576 + 0x8f, 0x13, 0x31, 0x75, 0x88, 0x88, 0x88, 0x88, 577 + 0x88, 0x88, 0xf8, 0x8f, 0x02, 0x20, 0x64, 0x88, 578 + 0x88, 0x88, 0x88, 0x88, 0x88, 0xf8, 0x00, 0x00, 579 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 580 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 581 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 582 + 0x00); 583 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01); 572 584 } 573 585 574 586 static const struct drm_display_mode rgb10max3_panel_mode = { ··· 591 611 .init_sequence = rgb10max3_panel_init_sequence, 592 612 }; 593 613 594 - static int gameforcechi_init_sequence(struct st7703 *ctx) 614 + static void gameforcechi_init_sequence(struct mipi_dsi_multi_context *dsi_ctx) 595 615 { 596 - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 597 - 598 616 /* 599 617 * Init sequence was supplied by the panel vendor. Panel will not 600 618 * respond to commands until it is brought out of sleep mode first. 601 619 */ 602 620 603 - mipi_dsi_dcs_exit_sleep_mode(dsi); 604 - msleep(250); 621 + mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx); 622 + mipi_dsi_msleep(dsi_ctx, 250); 605 623 606 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 607 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x31, 0x81, 0x05, 0xf9, 608 - 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 609 - 0x00, 0x00, 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 610 - 0x00, 0x02, 0x4f, 0xd1, 0x00, 0x00, 0x37); 611 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25); 612 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 613 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x0c, 0x10, 0x0a, 614 - 0x50, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 615 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 616 - 0x00, 0x00, 0x08, 0x70, 0x00); 617 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x46); 618 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b); 619 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80); 620 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x00, 0x13, 0xf0); 621 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, 622 - 0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 623 - 0xc0, 0x10); 624 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x53, 0x00, 0x1e, 625 - 0x1e, 0x77, 0xe1, 0xcc, 0xdd, 0x67, 0x77, 0x33, 626 - 0x33); 627 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x10, 0x10); 628 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x6c, 0x7c); 629 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0x08, 0x00, 0x0e, 0x00, 630 - 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x10, 631 - 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00, 632 - 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 633 - 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88, 634 - 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35, 635 - 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 636 - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 637 - 0x00, 0x00, 0x00); 638 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02, 639 - 0x13, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 640 - 0x80, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88, 641 - 0x88, 0x88, 0x88, 0x81, 0x88, 0xba, 0x06, 0x42, 642 - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x10, 643 - 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 644 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 645 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 646 - 0x00); 647 - mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0b, 648 - 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0x0a, 0x0b, 649 - 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18, 0x00, 0x07, 650 - 0x0b, 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0xa0, 651 - 0x0b, 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18); 652 - 653 - return 0; 624 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83); 625 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x31, 0x81, 0x05, 0xf9, 626 + 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 627 + 0x00, 0x00, 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 628 + 0x00, 0x02, 0x4f, 0xd1, 0x00, 0x00, 0x37); 629 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25); 630 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00); 631 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x0c, 0x10, 0x0a, 632 + 0x50, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00); 633 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50, 634 + 0x00, 0x00, 0x08, 0x70, 0x00); 635 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x46); 636 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b); 637 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80); 638 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x00, 0x13, 0xf0); 639 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b, 640 + 0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 641 + 0xc0, 0x10); 642 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x53, 0x00, 0x1e, 643 + 0x1e, 0x77, 0xe1, 0xcc, 0xdd, 0x67, 0x77, 0x33, 644 + 0x33); 645 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x10, 0x10); 646 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x6c, 0x7c); 647 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0x08, 0x00, 0x0e, 0x00, 648 + 0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x10, 649 + 0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00, 650 + 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 651 + 0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88, 652 + 0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35, 653 + 0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 654 + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 655 + 0x00, 0x00, 0x00); 656 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02, 657 + 0x13, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 658 + 0x80, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88, 659 + 0x88, 0x88, 0x88, 0x81, 0x88, 0xba, 0x06, 0x42, 660 + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x10, 661 + 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 662 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 663 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 664 + 0x00); 665 + mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0b, 666 + 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0x0a, 0x0b, 667 + 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18, 0x00, 0x07, 668 + 0x0b, 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0xa0, 669 + 0x0b, 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18); 654 670 } 655 671 656 672 static const struct drm_display_mode gameforcechi_mode = { ··· 677 701 { 678 702 struct st7703 *ctx = panel_to_st7703(panel); 679 703 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 680 - int ret; 704 + struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi}; 681 705 682 - ret = ctx->desc->init_sequence(ctx); 683 - if (ret < 0) { 684 - dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); 685 - return ret; 686 - } 706 + ctx->desc->init_sequence(&dsi_ctx); 687 707 688 - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 689 - if (ret < 0) { 690 - dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret); 691 - return ret; 692 - } 708 + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); 693 709 694 710 /* It takes the controller 120 msec to wake up after sleep. */ 695 - msleep(120); 711 + mipi_dsi_msleep(&dsi_ctx, 120); 696 712 697 - ret = mipi_dsi_dcs_set_display_on(dsi); 698 - if (ret) 699 - return ret; 713 + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); 700 714 701 - dev_dbg(ctx->dev, "Panel init sequence done\n"); 715 + if (!dsi_ctx.accum_err) 716 + dev_dbg(ctx->dev, "Panel init sequence done\n"); 702 717 703 - return 0; 718 + return dsi_ctx.accum_err; 704 719 } 705 720 706 721 static int st7703_disable(struct drm_panel *panel) 707 722 { 708 723 struct st7703 *ctx = panel_to_st7703(panel); 709 724 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 710 - int ret; 725 + struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi}; 711 726 712 - ret = mipi_dsi_dcs_set_display_off(dsi); 713 - if (ret < 0) 714 - dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret); 727 + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); 715 728 716 - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 717 - if (ret < 0) 718 - dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret); 729 + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); 719 730 720 731 /* It takes the controller 120 msec to enter sleep mode. */ 721 - msleep(120); 732 + mipi_dsi_msleep(&dsi_ctx, 120); 722 733 723 - return 0; 734 + return dsi_ctx.accum_err; 724 735 } 725 736 726 737 static int st7703_unprepare(struct drm_panel *panel) ··· 803 840 { 804 841 struct st7703 *ctx = data; 805 842 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 843 + struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi}; 806 844 807 845 dev_dbg(ctx->dev, "Setting all pixels on\n"); 808 - mipi_dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON); 809 - msleep(val * 1000); 846 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, ST7703_CMD_ALL_PIXEL_ON); 847 + mipi_dsi_msleep(&dsi_ctx, val * 1000); 810 848 811 849 /* 812 850 * Reset the panel to get video back. NOTE: This isn't a ··· 820 856 drm_panel_prepare(&ctx->panel); 821 857 drm_panel_enable(&ctx->panel); 822 858 823 - return 0; 859 + return dsi_ctx.accum_err; 824 860 } 825 861 826 862 DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL,
+206 -225
drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c
··· 44 44 static int truly_nt35521_on(struct truly_nt35521 *ctx) 45 45 { 46 46 struct mipi_dsi_device *dsi = ctx->dsi; 47 - struct device *dev = &dsi->dev; 48 - int ret; 47 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; 49 48 50 49 dsi->mode_flags |= MIPI_DSI_MODE_LPM; 51 50 52 - mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00); 53 - mipi_dsi_generic_write_seq(dsi, 0xff, 0xaa, 0x55, 0xa5, 0x80); 54 - mipi_dsi_generic_write_seq(dsi, 0x6f, 0x11, 0x00); 55 - mipi_dsi_generic_write_seq(dsi, 0xf7, 0x20, 0x00); 56 - mipi_dsi_generic_write_seq(dsi, 0x6f, 0x01); 57 - mipi_dsi_generic_write_seq(dsi, 0xb1, 0x21); 58 - mipi_dsi_generic_write_seq(dsi, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01); 59 - mipi_dsi_generic_write_seq(dsi, 0xb8, 0x01, 0x02, 0x0c, 0x02); 60 - mipi_dsi_generic_write_seq(dsi, 0xbb, 0x11, 0x11); 61 - mipi_dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x00); 62 - mipi_dsi_generic_write_seq(dsi, 0xb6, 0x02); 63 - mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01); 64 - mipi_dsi_generic_write_seq(dsi, 0xb0, 0x09, 0x09); 65 - mipi_dsi_generic_write_seq(dsi, 0xb1, 0x09, 0x09); 66 - mipi_dsi_generic_write_seq(dsi, 0xbc, 0x8c, 0x00); 67 - mipi_dsi_generic_write_seq(dsi, 0xbd, 0x8c, 0x00); 68 - mipi_dsi_generic_write_seq(dsi, 0xca, 0x00); 69 - mipi_dsi_generic_write_seq(dsi, 0xc0, 0x04); 70 - mipi_dsi_generic_write_seq(dsi, 0xbe, 0xb5); 71 - mipi_dsi_generic_write_seq(dsi, 0xb3, 0x35, 0x35); 72 - mipi_dsi_generic_write_seq(dsi, 0xb4, 0x25, 0x25); 73 - mipi_dsi_generic_write_seq(dsi, 0xb9, 0x43, 0x43); 74 - mipi_dsi_generic_write_seq(dsi, 0xba, 0x24, 0x24); 75 - mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02); 76 - mipi_dsi_generic_write_seq(dsi, 0xee, 0x03); 77 - mipi_dsi_generic_write_seq(dsi, 0xb0, 78 - 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3, 79 - 0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11); 80 - mipi_dsi_generic_write_seq(dsi, 0xb1, 81 - 0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3, 82 - 0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77); 83 - mipi_dsi_generic_write_seq(dsi, 0xb2, 84 - 0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c, 85 - 0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90); 86 - mipi_dsi_generic_write_seq(dsi, 0xb3, 0x03, 0x96, 0x03, 0x98); 87 - mipi_dsi_generic_write_seq(dsi, 0xb4, 88 - 0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9, 89 - 0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02); 90 - mipi_dsi_generic_write_seq(dsi, 0xb5, 91 - 0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf, 92 - 0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76); 93 - mipi_dsi_generic_write_seq(dsi, 0xb6, 94 - 0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c, 95 - 0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2); 96 - mipi_dsi_generic_write_seq(dsi, 0xb7, 0x03, 0xb8, 0x03, 0xba); 97 - mipi_dsi_generic_write_seq(dsi, 0xb8, 98 - 0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a, 99 - 0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9); 100 - mipi_dsi_generic_write_seq(dsi, 0xb9, 101 - 0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3, 102 - 0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67); 103 - mipi_dsi_generic_write_seq(dsi, 0xba, 104 - 0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31, 105 - 0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4); 106 - mipi_dsi_generic_write_seq(dsi, 0xbb, 0x03, 0xf6, 0x03, 0xf7); 107 - mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03); 108 - mipi_dsi_generic_write_seq(dsi, 0xb0, 0x22, 0x00); 109 - mipi_dsi_generic_write_seq(dsi, 0xb1, 0x22, 0x00); 110 - mipi_dsi_generic_write_seq(dsi, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00); 111 - mipi_dsi_generic_write_seq(dsi, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00); 112 - mipi_dsi_generic_write_seq(dsi, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00); 113 - mipi_dsi_generic_write_seq(dsi, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00); 114 - mipi_dsi_generic_write_seq(dsi, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00); 115 - mipi_dsi_generic_write_seq(dsi, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00); 116 - mipi_dsi_generic_write_seq(dsi, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00); 117 - mipi_dsi_generic_write_seq(dsi, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00); 118 - mipi_dsi_generic_write_seq(dsi, 0xc0, 0x00, 0x34, 0x00, 0x00); 119 - mipi_dsi_generic_write_seq(dsi, 0xc1, 0x00, 0x00, 0x34, 0x00); 120 - mipi_dsi_generic_write_seq(dsi, 0xc2, 0x00, 0x00, 0x34, 0x00); 121 - mipi_dsi_generic_write_seq(dsi, 0xc3, 0x00, 0x00, 0x34, 0x00); 122 - mipi_dsi_generic_write_seq(dsi, 0xc4, 0x60); 123 - mipi_dsi_generic_write_seq(dsi, 0xc5, 0xc0); 124 - mipi_dsi_generic_write_seq(dsi, 0xc6, 0x00); 125 - mipi_dsi_generic_write_seq(dsi, 0xc7, 0x00); 126 - mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05); 127 - mipi_dsi_generic_write_seq(dsi, 0xb0, 0x17, 0x06); 128 - mipi_dsi_generic_write_seq(dsi, 0xb1, 0x17, 0x06); 129 - mipi_dsi_generic_write_seq(dsi, 0xb2, 0x17, 0x06); 130 - mipi_dsi_generic_write_seq(dsi, 0xb3, 0x17, 0x06); 131 - mipi_dsi_generic_write_seq(dsi, 0xb4, 0x17, 0x06); 132 - mipi_dsi_generic_write_seq(dsi, 0xb5, 0x17, 0x06); 133 - mipi_dsi_generic_write_seq(dsi, 0xb6, 0x17, 0x06); 134 - mipi_dsi_generic_write_seq(dsi, 0xb7, 0x17, 0x06); 135 - mipi_dsi_generic_write_seq(dsi, 0xb8, 0x00); 136 - mipi_dsi_generic_write_seq(dsi, 0xb9, 0x00, 0x03); 137 - mipi_dsi_generic_write_seq(dsi, 0xba, 0x00, 0x00); 138 - mipi_dsi_generic_write_seq(dsi, 0xbb, 0x02, 0x03); 139 - mipi_dsi_generic_write_seq(dsi, 0xbc, 0x02, 0x03); 140 - mipi_dsi_generic_write_seq(dsi, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03); 141 - mipi_dsi_generic_write_seq(dsi, 0xc0, 0x0b); 142 - mipi_dsi_generic_write_seq(dsi, 0xc1, 0x09); 143 - mipi_dsi_generic_write_seq(dsi, 0xc2, 0xa6); 144 - mipi_dsi_generic_write_seq(dsi, 0xc3, 0x05); 145 - mipi_dsi_generic_write_seq(dsi, 0xc4, 0x00); 146 - mipi_dsi_generic_write_seq(dsi, 0xc5, 0x02); 147 - mipi_dsi_generic_write_seq(dsi, 0xc6, 0x22); 148 - mipi_dsi_generic_write_seq(dsi, 0xc7, 0x03); 149 - mipi_dsi_generic_write_seq(dsi, 0xc8, 0x07, 0x20); 150 - mipi_dsi_generic_write_seq(dsi, 0xc9, 0x03, 0x20); 151 - mipi_dsi_generic_write_seq(dsi, 0xca, 0x01, 0x60); 152 - mipi_dsi_generic_write_seq(dsi, 0xcb, 0x01, 0x60); 153 - mipi_dsi_generic_write_seq(dsi, 0xcc, 0x00, 0x00, 0x02); 154 - mipi_dsi_generic_write_seq(dsi, 0xcd, 0x00, 0x00, 0x02); 155 - mipi_dsi_generic_write_seq(dsi, 0xce, 0x00, 0x00, 0x02); 156 - mipi_dsi_generic_write_seq(dsi, 0xcf, 0x00, 0x00, 0x02); 157 - mipi_dsi_generic_write_seq(dsi, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10); 158 - mipi_dsi_generic_write_seq(dsi, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10); 159 - mipi_dsi_generic_write_seq(dsi, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10); 160 - mipi_dsi_generic_write_seq(dsi, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10); 161 - mipi_dsi_generic_write_seq(dsi, 0xd0, 162 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 163 - mipi_dsi_generic_write_seq(dsi, 0xd5, 164 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 165 - 0x00, 0x00, 0x00); 166 - mipi_dsi_generic_write_seq(dsi, 0xd6, 167 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 168 - 0x00, 0x00, 0x00); 169 - mipi_dsi_generic_write_seq(dsi, 0xd7, 170 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 171 - 0x00, 0x00, 0x00); 172 - mipi_dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00); 173 - mipi_dsi_generic_write_seq(dsi, 0xe5, 0x06); 174 - mipi_dsi_generic_write_seq(dsi, 0xe6, 0x06); 175 - mipi_dsi_generic_write_seq(dsi, 0xe7, 0x00); 176 - mipi_dsi_generic_write_seq(dsi, 0xe8, 0x06); 177 - mipi_dsi_generic_write_seq(dsi, 0xe9, 0x06); 178 - mipi_dsi_generic_write_seq(dsi, 0xea, 0x06); 179 - mipi_dsi_generic_write_seq(dsi, 0xeb, 0x00); 180 - mipi_dsi_generic_write_seq(dsi, 0xec, 0x00); 181 - mipi_dsi_generic_write_seq(dsi, 0xed, 0x30); 182 - mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06); 183 - mipi_dsi_generic_write_seq(dsi, 0xb0, 0x31, 0x31); 184 - mipi_dsi_generic_write_seq(dsi, 0xb1, 0x31, 0x31); 185 - mipi_dsi_generic_write_seq(dsi, 0xb2, 0x2d, 0x2e); 186 - mipi_dsi_generic_write_seq(dsi, 0xb3, 0x31, 0x34); 187 - mipi_dsi_generic_write_seq(dsi, 0xb4, 0x29, 0x2a); 188 - mipi_dsi_generic_write_seq(dsi, 0xb5, 0x12, 0x10); 189 - mipi_dsi_generic_write_seq(dsi, 0xb6, 0x18, 0x16); 190 - mipi_dsi_generic_write_seq(dsi, 0xb7, 0x00, 0x02); 191 - mipi_dsi_generic_write_seq(dsi, 0xb8, 0x08, 0x31); 192 - mipi_dsi_generic_write_seq(dsi, 0xb9, 0x31, 0x31); 193 - mipi_dsi_generic_write_seq(dsi, 0xba, 0x31, 0x31); 194 - mipi_dsi_generic_write_seq(dsi, 0xbb, 0x31, 0x08); 195 - mipi_dsi_generic_write_seq(dsi, 0xbc, 0x03, 0x01); 196 - mipi_dsi_generic_write_seq(dsi, 0xbd, 0x17, 0x19); 197 - mipi_dsi_generic_write_seq(dsi, 0xbe, 0x11, 0x13); 198 - mipi_dsi_generic_write_seq(dsi, 0xbf, 0x2a, 0x29); 199 - mipi_dsi_generic_write_seq(dsi, 0xc0, 0x34, 0x31); 200 - mipi_dsi_generic_write_seq(dsi, 0xc1, 0x2e, 0x2d); 201 - mipi_dsi_generic_write_seq(dsi, 0xc2, 0x31, 0x31); 202 - mipi_dsi_generic_write_seq(dsi, 0xc3, 0x31, 0x31); 203 - mipi_dsi_generic_write_seq(dsi, 0xc4, 0x31, 0x31); 204 - mipi_dsi_generic_write_seq(dsi, 0xc5, 0x31, 0x31); 205 - mipi_dsi_generic_write_seq(dsi, 0xc6, 0x2e, 0x2d); 206 - mipi_dsi_generic_write_seq(dsi, 0xc7, 0x31, 0x34); 207 - mipi_dsi_generic_write_seq(dsi, 0xc8, 0x29, 0x2a); 208 - mipi_dsi_generic_write_seq(dsi, 0xc9, 0x17, 0x19); 209 - mipi_dsi_generic_write_seq(dsi, 0xca, 0x11, 0x13); 210 - mipi_dsi_generic_write_seq(dsi, 0xcb, 0x03, 0x01); 211 - mipi_dsi_generic_write_seq(dsi, 0xcc, 0x08, 0x31); 212 - mipi_dsi_generic_write_seq(dsi, 0xcd, 0x31, 0x31); 213 - mipi_dsi_generic_write_seq(dsi, 0xce, 0x31, 0x31); 214 - mipi_dsi_generic_write_seq(dsi, 0xcf, 0x31, 0x08); 215 - mipi_dsi_generic_write_seq(dsi, 0xd0, 0x00, 0x02); 216 - mipi_dsi_generic_write_seq(dsi, 0xd1, 0x12, 0x10); 217 - mipi_dsi_generic_write_seq(dsi, 0xd2, 0x18, 0x16); 218 - mipi_dsi_generic_write_seq(dsi, 0xd3, 0x2a, 0x29); 219 - mipi_dsi_generic_write_seq(dsi, 0xd4, 0x34, 0x31); 220 - mipi_dsi_generic_write_seq(dsi, 0xd5, 0x2d, 0x2e); 221 - mipi_dsi_generic_write_seq(dsi, 0xd6, 0x31, 0x31); 222 - mipi_dsi_generic_write_seq(dsi, 0xd7, 0x31, 0x31); 223 - mipi_dsi_generic_write_seq(dsi, 0xe5, 0x31, 0x31); 224 - mipi_dsi_generic_write_seq(dsi, 0xe6, 0x31, 0x31); 225 - mipi_dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00); 226 - mipi_dsi_generic_write_seq(dsi, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00); 227 - mipi_dsi_generic_write_seq(dsi, 0xe7, 0x00); 228 - mipi_dsi_generic_write_seq(dsi, 0x6f, 0x02); 229 - mipi_dsi_generic_write_seq(dsi, 0xf7, 0x47); 230 - mipi_dsi_generic_write_seq(dsi, 0x6f, 0x0a); 231 - mipi_dsi_generic_write_seq(dsi, 0xf7, 0x02); 232 - mipi_dsi_generic_write_seq(dsi, 0x6f, 0x17); 233 - mipi_dsi_generic_write_seq(dsi, 0xf4, 0x60); 234 - mipi_dsi_generic_write_seq(dsi, 0x6f, 0x01); 235 - mipi_dsi_generic_write_seq(dsi, 0xf9, 0x46); 236 - mipi_dsi_generic_write_seq(dsi, 0x6f, 0x11); 237 - mipi_dsi_generic_write_seq(dsi, 0xf3, 0x01); 238 - mipi_dsi_generic_write_seq(dsi, 0x35, 0x00); 239 - mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00); 240 - mipi_dsi_generic_write_seq(dsi, 0xd9, 0x02, 0x03, 0x00); 241 - mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00); 242 - mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00); 243 - mipi_dsi_generic_write_seq(dsi, 0xb1, 0x6c, 0x21); 244 - mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00); 245 - mipi_dsi_generic_write_seq(dsi, 0x35, 0x00); 51 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00); 52 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x80); 53 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x11, 0x00); 54 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x20, 0x00); 55 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x01); 56 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x21); 57 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01); 58 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x01, 0x02, 0x0c, 0x02); 59 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x11, 0x11); 60 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x00, 0x00); 61 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x02); 62 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01); 63 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x09, 0x09); 64 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x09, 0x09); 65 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x8c, 0x00); 66 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x8c, 0x00); 67 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x00); 68 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x04); 69 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbe, 0xb5); 70 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x35, 0x35); 71 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x25, 0x25); 72 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x43, 0x43); 73 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x24, 0x24); 74 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02); 75 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xee, 0x03); 76 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 77 + 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3, 78 + 0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11); 79 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 80 + 0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3, 81 + 0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77); 82 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 83 + 0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c, 84 + 0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90); 85 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x03, 0x96, 0x03, 0x98); 86 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 87 + 0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9, 88 + 0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02); 89 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 90 + 0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf, 91 + 0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76); 92 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 93 + 0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c, 94 + 0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2); 95 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x03, 0xb8, 0x03, 0xba); 96 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 97 + 0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a, 98 + 0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9); 99 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 100 + 0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3, 101 + 0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67); 102 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 103 + 0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31, 104 + 0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4); 105 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x03, 0xf6, 0x03, 0xf7); 106 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03); 107 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x22, 0x00); 108 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x22, 0x00); 109 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00); 110 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00); 111 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00); 112 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00); 113 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00); 114 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00); 115 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00); 116 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00); 117 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x00, 0x34, 0x00, 0x00); 118 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x00, 0x00, 0x34, 0x00); 119 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0x00, 0x00, 0x34, 0x00); 120 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x00, 0x00, 0x34, 0x00); 121 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x60); 122 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0xc0); 123 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x00); 124 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x00); 125 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05); 126 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x17, 0x06); 127 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x17, 0x06); 128 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x17, 0x06); 129 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x17, 0x06); 130 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x17, 0x06); 131 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x17, 0x06); 132 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x17, 0x06); 133 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x17, 0x06); 134 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x00); 135 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x00, 0x03); 136 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x00, 0x00); 137 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x02, 0x03); 138 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x02, 0x03); 139 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03); 140 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x0b); 141 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x09); 142 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0xa6); 143 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x05); 144 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x00); 145 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x02); 146 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x22); 147 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x03); 148 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc8, 0x07, 0x20); 149 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc9, 0x03, 0x20); 150 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x01, 0x60); 151 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, 0x01, 0x60); 152 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, 0x00, 0x00, 0x02); 153 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcd, 0x00, 0x00, 0x02); 154 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, 0x00, 0x00, 0x02); 155 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, 0x00, 0x00, 0x02); 156 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10); 157 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10); 158 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10); 159 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10); 160 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd0, 161 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 162 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd5, 163 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 164 + 0x00, 0x00, 0x00); 165 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd6, 166 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 167 + 0x00, 0x00, 0x00); 168 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd7, 169 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 170 + 0x00, 0x00, 0x00); 171 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00); 172 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe5, 0x06); 173 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe6, 0x06); 174 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe7, 0x00); 175 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe8, 0x06); 176 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe9, 0x06); 177 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xea, 0x06); 178 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xeb, 0x00); 179 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xec, 0x00); 180 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xed, 0x30); 181 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06); 182 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x31, 0x31); 183 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x31, 0x31); 184 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x2d, 0x2e); 185 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x31, 0x34); 186 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x29, 0x2a); 187 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x12, 0x10); 188 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x18, 0x16); 189 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x00, 0x02); 190 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x08, 0x31); 191 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x31, 0x31); 192 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x31, 0x31); 193 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x31, 0x08); 194 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x03, 0x01); 195 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x17, 0x19); 196 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbe, 0x11, 0x13); 197 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbf, 0x2a, 0x29); 198 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x34, 0x31); 199 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x2e, 0x2d); 200 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0x31, 0x31); 201 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x31, 0x31); 202 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x31, 0x31); 203 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x31, 0x31); 204 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x2e, 0x2d); 205 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x31, 0x34); 206 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc8, 0x29, 0x2a); 207 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc9, 0x17, 0x19); 208 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x11, 0x13); 209 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, 0x03, 0x01); 210 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, 0x08, 0x31); 211 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcd, 0x31, 0x31); 212 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, 0x31, 0x31); 213 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, 0x31, 0x08); 214 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd0, 0x00, 0x02); 215 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd1, 0x12, 0x10); 216 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd2, 0x18, 0x16); 217 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd3, 0x2a, 0x29); 218 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd4, 0x34, 0x31); 219 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd5, 0x2d, 0x2e); 220 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd6, 0x31, 0x31); 221 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd7, 0x31, 0x31); 222 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe5, 0x31, 0x31); 223 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe6, 0x31, 0x31); 224 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00); 225 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00); 226 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe7, 0x00); 227 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x02); 228 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x47); 229 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x0a); 230 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x02); 231 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x17); 232 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf4, 0x60); 233 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x01); 234 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf9, 0x46); 235 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x11); 236 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf3, 0x01); 237 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x35, 0x00); 238 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00); 239 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd9, 0x02, 0x03, 0x00); 240 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00); 241 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00); 242 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x6c, 0x21); 243 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00); 244 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x35, 0x00); 246 245 247 - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 248 - if (ret < 0) { 249 - dev_err(dev, "Failed to exit sleep mode: %d\n", ret); 250 - return ret; 251 - } 252 - msleep(120); 246 + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); 247 + mipi_dsi_msleep(&dsi_ctx, 120); 248 + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); 253 249 254 - ret = mipi_dsi_dcs_set_display_on(dsi); 255 - if (ret < 0) { 256 - dev_err(dev, "Failed to set display on: %d\n", ret); 257 - return ret; 258 - } 259 250 usleep_range(1000, 2000); 260 251 261 - mipi_dsi_generic_write_seq(dsi, 0x53, 0x24); 252 + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x53, 0x24); 262 253 263 - return 0; 254 + return dsi_ctx.accum_err; 264 255 } 265 256 266 257 static int truly_nt35521_off(struct truly_nt35521 *ctx) 267 258 { 268 259 struct mipi_dsi_device *dsi = ctx->dsi; 269 - struct device *dev = &dsi->dev; 270 - int ret; 260 + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; 271 261 272 262 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 273 263 274 - ret = mipi_dsi_dcs_set_display_off(dsi); 275 - if (ret < 0) { 276 - dev_err(dev, "Failed to set display off: %d\n", ret); 277 - return ret; 278 - } 279 - msleep(50); 264 + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); 265 + mipi_dsi_msleep(&dsi_ctx, 50); 266 + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); 267 + mipi_dsi_msleep(&dsi_ctx, 150); 280 268 281 - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 282 - if (ret < 0) { 283 - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); 284 - return ret; 285 - } 286 - msleep(150); 287 - 288 - return 0; 269 + return dsi_ctx.accum_err; 289 270 } 290 271 291 272 static int truly_nt35521_prepare(struct drm_panel *panel)
+3
drivers/gpu/drm/qxl/qxl_display.c
··· 236 236 return 0; 237 237 238 238 mode = drm_cvt_mode(dev, width, height, 60, false, false, false); 239 + if (!mode) 240 + return 0; 241 + 239 242 if (preferred) 240 243 mode->type |= DRM_MODE_TYPE_PREFERRED; 241 244 mode->hdisplay = width;
+7 -19
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
··· 13 13 #include <linux/of.h> 14 14 #include <linux/of_graph.h> 15 15 #include <linux/platform_device.h> 16 + #include <linux/pm_runtime.h> 16 17 #include <linux/regmap.h> 17 18 #include <linux/reset.h> 18 19 #include <linux/clk.h> ··· 93 92 return 0; 94 93 } 95 94 96 - static int rockchip_dp_poweron_start(struct analogix_dp_plat_data *plat_data) 95 + static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data) 97 96 { 98 97 struct rockchip_dp_device *dp = pdata_encoder_to_dp(plat_data); 99 98 int ret; ··· 398 397 dp->data = dp_data; 399 398 dp->plat_data.panel = panel; 400 399 dp->plat_data.dev_type = dp->data->chip_type; 401 - dp->plat_data.power_on_start = rockchip_dp_poweron_start; 400 + dp->plat_data.power_on = rockchip_dp_poweron; 402 401 dp->plat_data.power_off = rockchip_dp_powerdown; 403 402 dp->plat_data.get_modes = rockchip_dp_get_modes; 404 403 ··· 414 413 415 414 ret = component_add(dev, &rockchip_dp_component_ops); 416 415 if (ret) 417 - goto err_dp_remove; 416 + return ret; 418 417 419 418 return 0; 420 - 421 - err_dp_remove: 422 - analogix_dp_remove(dp->adp); 423 - return ret; 424 419 } 425 420 426 421 static void rockchip_dp_remove(struct platform_device *pdev) 427 422 { 428 - struct rockchip_dp_device *dp = platform_get_drvdata(pdev); 429 - 430 423 component_del(&pdev->dev, &rockchip_dp_component_ops); 431 - analogix_dp_remove(dp->adp); 432 424 } 433 425 434 - #ifdef CONFIG_PM_SLEEP 435 426 static int rockchip_dp_suspend(struct device *dev) 436 427 { 437 428 struct rockchip_dp_device *dp = dev_get_drvdata(dev); ··· 443 450 444 451 return analogix_dp_resume(dp->adp); 445 452 } 446 - #endif 447 453 448 - static const struct dev_pm_ops rockchip_dp_pm_ops = { 449 - #ifdef CONFIG_PM_SLEEP 450 - .suspend_late = rockchip_dp_suspend, 451 - .resume_early = rockchip_dp_resume, 452 - #endif 453 - }; 454 + static DEFINE_RUNTIME_DEV_PM_OPS(rockchip_dp_pm_ops, rockchip_dp_suspend, 455 + rockchip_dp_resume, NULL); 454 456 455 457 static const struct rockchip_dp_chip_data rk3399_edp = { 456 458 .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, ··· 473 485 .remove_new = rockchip_dp_remove, 474 486 .driver = { 475 487 .name = "rockchip-dp", 476 - .pm = &rockchip_dp_pm_ops, 488 + .pm = pm_ptr(&rockchip_dp_pm_ops), 477 489 .of_match_table = rockchip_dp_dt_ids, 478 490 }, 479 491 };
+1
drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
··· 1740 1740 ); 1741 1741 1742 1742 MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>"); 1743 + MODULE_DESCRIPTION("Kunit test for drm_hdmi_state_helper functions"); 1743 1744 MODULE_LICENSE("GPL");
-1
drivers/gpu/drm/ttm/tests/.kunitconfig
··· 1 1 CONFIG_KUNIT=y 2 2 CONFIG_DRM=y 3 - CONFIG_DRM_KUNIT_TEST_HELPERS=y 4 3 CONFIG_DRM_TTM_KUNIT_TEST=y
+2
drivers/gpu/drm/ttm/tests/Makefile
··· 6 6 ttm_resource_test.o \ 7 7 ttm_tt_test.o \ 8 8 ttm_bo_test.o \ 9 + ttm_bo_validate_test.o \ 10 + ttm_mock_manager.o \ 9 11 ttm_kunit_helpers.o
+27
drivers/gpu/drm/ttm/tests/TODO
··· 1 + TODO 2 + ===== 3 + 4 + - Add a test case where the only evictable BO is busy 5 + - Update eviction tests so they use parametrized "from" memory type 6 + - Improve mock manager's implementation, e.g. allocate a block of 7 + dummy memory that can be used when testing page mapping functions 8 + - Suggestion: Add test cases with external BOs 9 + - Suggestion: randomize the number and size of tested buffers in 10 + ttm_bo_validate() 11 + - Agree on the naming convention 12 + - Rewrite the mock manager: drop use_tt and manage mock memory using 13 + drm_mm manager 14 + 15 + Notes and gotchas 16 + ================= 17 + 18 + - These tests are built and run with a UML kernel, because 19 + 1) We are interested in hardware-independent testing 20 + 2) We don't want to have actual DRM devices interacting with TTM 21 + at the same time as the test one. Getting these to work in 22 + parallel would require some time (...and that's a "todo" in itself!) 23 + - Triggering ttm_bo_vm_ops callbacks from KUnit (i.e. kernel) might be 24 + a challenge, but is worth trying. Look at selftests like 25 + i915/gem/selftests/i915_gem_mman.c for inspiration 26 + - The test suite uses UML where ioremap() call returns NULL, meaning that 27 + ttm_bo_ioremap() can't be tested, unless we find a way to stub it
+39 -24
drivers/gpu/drm/ttm/tests/ttm_bo_test.c
··· 18 18 19 19 #define BO_SIZE SZ_8K 20 20 21 + #ifdef CONFIG_PREEMPT_RT 22 + #define ww_mutex_base_lock(b) rt_mutex_lock(b) 23 + #else 24 + #define ww_mutex_base_lock(b) mutex_lock(b) 25 + #endif 26 + 21 27 struct ttm_bo_test_case { 22 28 const char *description; 23 29 bool interruptible; ··· 62 56 struct ttm_buffer_object *bo; 63 57 int err; 64 58 65 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 59 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 66 60 67 61 err = ttm_bo_reserve(bo, params->interruptible, params->no_wait, NULL); 68 62 KUNIT_ASSERT_EQ(test, err, 0); ··· 77 71 bool no_wait = true; 78 72 int err; 79 73 80 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 74 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 81 75 82 76 /* Let's lock it beforehand */ 83 77 dma_resv_lock(bo->base.resv, NULL); ··· 98 92 99 93 ww_acquire_init(&ctx, &reservation_ww_class); 100 94 101 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 95 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 102 96 103 97 err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx); 104 98 KUNIT_ASSERT_EQ(test, err, -EBUSY); ··· 116 110 117 111 ww_acquire_init(&ctx, &reservation_ww_class); 118 112 119 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 113 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 120 114 121 115 err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx); 122 116 KUNIT_ASSERT_EQ(test, err, 0); ··· 144 138 bool no_wait = false; 145 139 int err; 146 140 147 - bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 148 - bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 141 + bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 142 + bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 149 143 150 144 ww_acquire_init(&ctx1, &reservation_ww_class); 151 - mutex_lock(&bo2->base.resv->lock.base); 145 + ww_mutex_base_lock(&bo2->base.resv->lock.base); 152 146 153 147 /* The deadlock will be caught by WW mutex, don't warn about it */ 154 148 lock_release(&bo2->base.resv->lock.base.dep_map, 1); ··· 214 208 struct task_struct *task; 215 209 int err; 216 210 217 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 211 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 218 212 219 213 task = kthread_create(threaded_ttm_bo_reserve, bo, "ttm-bo-reserve"); 220 214 ··· 243 237 struct ttm_place *place; 244 238 struct ttm_resource_manager *man; 245 239 unsigned int bo_prio = TTM_MAX_BO_PRIORITY - 1; 246 - uint32_t mem_type = TTM_PL_SYSTEM; 240 + u32 mem_type = TTM_PL_SYSTEM; 247 241 int err; 248 242 249 243 place = ttm_place_kunit_init(test, mem_type, 0); ··· 255 249 KUNIT_ASSERT_EQ(test, err, 0); 256 250 priv->ttm_dev = ttm_dev; 257 251 258 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 252 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 259 253 bo->priority = bo_prio; 260 254 261 255 err = ttm_resource_alloc(bo, place, &res1); ··· 284 278 struct ttm_device *ttm_dev; 285 279 struct ttm_resource *res1, *res2; 286 280 struct ttm_place *place; 287 - uint32_t mem_type = TTM_PL_SYSTEM; 281 + u32 mem_type = TTM_PL_SYSTEM; 288 282 int err; 289 283 290 284 ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); ··· 294 288 KUNIT_ASSERT_EQ(test, err, 0); 295 289 priv->ttm_dev = ttm_dev; 296 290 297 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 291 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 298 292 place = ttm_place_kunit_init(test, mem_type, 0); 299 293 300 294 dma_resv_lock(bo->base.resv, NULL); ··· 327 321 struct ttm_resource *res1, *res2; 328 322 struct ttm_device *ttm_dev; 329 323 struct ttm_place *place; 330 - uint32_t mem_type = TTM_PL_SYSTEM; 324 + struct dma_resv *resv; 325 + u32 mem_type = TTM_PL_SYSTEM; 331 326 unsigned int bo_priority = 0; 332 327 int err; 333 328 ··· 339 332 ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL); 340 333 KUNIT_ASSERT_NOT_NULL(test, ttm_dev); 341 334 335 + resv = kunit_kzalloc(test, sizeof(*resv), GFP_KERNEL); 336 + KUNIT_ASSERT_NOT_NULL(test, ttm_dev); 337 + 342 338 err = ttm_device_kunit_init(priv, ttm_dev, false, false); 343 339 KUNIT_ASSERT_EQ(test, err, 0); 344 340 priv->ttm_dev = ttm_dev; 345 341 346 - bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 347 - bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 342 + dma_resv_init(resv); 343 + 344 + bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, resv); 345 + bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, resv); 348 346 349 347 dma_resv_lock(bo1->base.resv, NULL); 350 348 ttm_bo_set_bulk_move(bo1, &lru_bulk_move); ··· 375 363 376 364 ttm_resource_free(bo1, &res1); 377 365 ttm_resource_free(bo2, &res2); 366 + 367 + dma_resv_fini(resv); 378 368 } 379 369 380 370 static void ttm_bo_put_basic(struct kunit *test) ··· 386 372 struct ttm_resource *res; 387 373 struct ttm_device *ttm_dev; 388 374 struct ttm_place *place; 389 - uint32_t mem_type = TTM_PL_SYSTEM; 375 + u32 mem_type = TTM_PL_SYSTEM; 390 376 int err; 391 377 392 378 place = ttm_place_kunit_init(test, mem_type, 0); ··· 398 384 KUNIT_ASSERT_EQ(test, err, 0); 399 385 priv->ttm_dev = ttm_dev; 400 386 401 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 387 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 402 388 bo->type = ttm_bo_type_device; 403 389 404 390 err = ttm_resource_alloc(bo, place, &res); ··· 459 445 460 446 dma_fence_signal(fence); 461 447 462 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 448 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 463 449 bo->type = ttm_bo_type_device; 464 450 bo->base.resv = external_resv; 465 451 ··· 481 467 KUNIT_ASSERT_EQ(test, err, 0); 482 468 priv->ttm_dev = ttm_dev; 483 469 484 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 470 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 485 471 486 472 for (int i = 0; i < no_pins; i++) { 487 473 dma_resv_lock(bo->base.resv, NULL); ··· 501 487 struct ttm_resource *res; 502 488 struct ttm_device *ttm_dev; 503 489 struct ttm_place *place; 504 - uint32_t mem_type = TTM_PL_SYSTEM; 490 + u32 mem_type = TTM_PL_SYSTEM; 505 491 unsigned int bo_priority = 0; 506 492 int err; 507 493 ··· 516 502 KUNIT_ASSERT_EQ(test, err, 0); 517 503 priv->ttm_dev = ttm_dev; 518 504 519 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 505 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 520 506 521 507 err = ttm_resource_alloc(bo, place, &res); 522 508 KUNIT_ASSERT_EQ(test, err, 0); ··· 552 538 struct ttm_resource *res; 553 539 struct ttm_device *ttm_dev; 554 540 struct ttm_place *place; 555 - uint32_t mem_type = TTM_PL_SYSTEM; 541 + u32 mem_type = TTM_PL_SYSTEM; 556 542 unsigned int bo_priority = 0; 557 543 int err; 558 544 ··· 567 553 KUNIT_ASSERT_EQ(test, err, 0); 568 554 priv->ttm_dev = ttm_dev; 569 555 570 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 556 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 571 557 572 558 err = ttm_resource_alloc(bo, place, &res); 573 559 KUNIT_ASSERT_EQ(test, err, 0); ··· 633 619 634 620 kunit_test_suites(&ttm_bo_test_suite); 635 621 636 - MODULE_LICENSE("GPL"); 622 + MODULE_DESCRIPTION("KUnit tests for ttm_bo APIs"); 623 + MODULE_LICENSE("GPL and additional rights");
+1225
drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 AND MIT 2 + /* 3 + * Copyright © 2023 Intel Corporation 4 + */ 5 + #include <linux/delay.h> 6 + #include <linux/kthread.h> 7 + 8 + #include <drm/ttm/ttm_resource.h> 9 + #include <drm/ttm/ttm_placement.h> 10 + #include <drm/ttm/ttm_tt.h> 11 + 12 + #include "ttm_kunit_helpers.h" 13 + #include "ttm_mock_manager.h" 14 + 15 + #define BO_SIZE SZ_4K 16 + #define MANAGER_SIZE SZ_1M 17 + 18 + static struct spinlock fence_lock; 19 + 20 + struct ttm_bo_validate_test_case { 21 + const char *description; 22 + enum ttm_bo_type bo_type; 23 + u32 mem_type; 24 + bool with_ttm; 25 + bool no_gpu_wait; 26 + }; 27 + 28 + static struct ttm_placement *ttm_placement_kunit_init(struct kunit *test, 29 + struct ttm_place *places, 30 + unsigned int num_places) 31 + { 32 + struct ttm_placement *placement; 33 + 34 + placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL); 35 + KUNIT_ASSERT_NOT_NULL(test, placement); 36 + 37 + placement->num_placement = num_places; 38 + placement->placement = places; 39 + 40 + return placement; 41 + } 42 + 43 + static const char *fence_name(struct dma_fence *f) 44 + { 45 + return "ttm-bo-validate-fence"; 46 + } 47 + 48 + static const struct dma_fence_ops fence_ops = { 49 + .get_driver_name = fence_name, 50 + .get_timeline_name = fence_name, 51 + }; 52 + 53 + static struct dma_fence *alloc_mock_fence(struct kunit *test) 54 + { 55 + struct dma_fence *fence; 56 + 57 + fence = kunit_kzalloc(test, sizeof(*fence), GFP_KERNEL); 58 + KUNIT_ASSERT_NOT_NULL(test, fence); 59 + 60 + dma_fence_init(fence, &fence_ops, &fence_lock, 0, 0); 61 + 62 + return fence; 63 + } 64 + 65 + static void dma_resv_kunit_active_fence_init(struct kunit *test, 66 + struct dma_resv *resv, 67 + enum dma_resv_usage usage) 68 + { 69 + struct dma_fence *fence; 70 + 71 + fence = alloc_mock_fence(test); 72 + dma_fence_enable_sw_signaling(fence); 73 + 74 + dma_resv_lock(resv, NULL); 75 + dma_resv_reserve_fences(resv, 1); 76 + dma_resv_add_fence(resv, fence, usage); 77 + dma_resv_unlock(resv); 78 + } 79 + 80 + static void ttm_bo_validate_case_desc(const struct ttm_bo_validate_test_case *t, 81 + char *desc) 82 + { 83 + strscpy(desc, t->description, KUNIT_PARAM_DESC_SIZE); 84 + } 85 + 86 + static const struct ttm_bo_validate_test_case ttm_bo_type_cases[] = { 87 + { 88 + .description = "Buffer object for userspace", 89 + .bo_type = ttm_bo_type_device, 90 + }, 91 + { 92 + .description = "Kernel buffer object", 93 + .bo_type = ttm_bo_type_kernel, 94 + }, 95 + { 96 + .description = "Shared buffer object", 97 + .bo_type = ttm_bo_type_sg, 98 + }, 99 + }; 100 + 101 + KUNIT_ARRAY_PARAM(ttm_bo_types, ttm_bo_type_cases, 102 + ttm_bo_validate_case_desc); 103 + 104 + static void ttm_bo_init_reserved_sys_man(struct kunit *test) 105 + { 106 + const struct ttm_bo_validate_test_case *params = test->param_value; 107 + struct ttm_test_devices *priv = test->priv; 108 + enum ttm_bo_type bo_type = params->bo_type; 109 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 110 + struct ttm_operation_ctx ctx = { }; 111 + struct ttm_placement *placement; 112 + struct ttm_buffer_object *bo; 113 + struct ttm_place *place; 114 + int err; 115 + 116 + bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL); 117 + KUNIT_ASSERT_NOT_NULL(test, bo); 118 + 119 + place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0); 120 + placement = ttm_placement_kunit_init(test, place, 1); 121 + 122 + drm_gem_private_object_init(priv->drm, &bo->base, size); 123 + 124 + err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement, 125 + PAGE_SIZE, &ctx, NULL, NULL, 126 + &dummy_ttm_bo_destroy); 127 + dma_resv_unlock(bo->base.resv); 128 + 129 + KUNIT_EXPECT_EQ(test, err, 0); 130 + KUNIT_EXPECT_EQ(test, kref_read(&bo->kref), 1); 131 + KUNIT_EXPECT_PTR_EQ(test, bo->bdev, priv->ttm_dev); 132 + KUNIT_EXPECT_EQ(test, bo->type, bo_type); 133 + KUNIT_EXPECT_EQ(test, bo->page_alignment, PAGE_SIZE); 134 + KUNIT_EXPECT_PTR_EQ(test, bo->destroy, &dummy_ttm_bo_destroy); 135 + KUNIT_EXPECT_EQ(test, bo->pin_count, 0); 136 + KUNIT_EXPECT_NULL(test, bo->bulk_move); 137 + KUNIT_EXPECT_NOT_NULL(test, bo->ttm); 138 + KUNIT_EXPECT_FALSE(test, ttm_tt_is_populated(bo->ttm)); 139 + KUNIT_EXPECT_NOT_NULL(test, (void *)bo->base.resv->fences); 140 + KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size); 141 + 142 + if (bo_type != ttm_bo_type_kernel) 143 + KUNIT_EXPECT_TRUE(test, 144 + drm_mm_node_allocated(&bo->base.vma_node.vm_node)); 145 + 146 + ttm_resource_free(bo, &bo->resource); 147 + ttm_bo_put(bo); 148 + } 149 + 150 + static void ttm_bo_init_reserved_mock_man(struct kunit *test) 151 + { 152 + const struct ttm_bo_validate_test_case *params = test->param_value; 153 + enum ttm_bo_type bo_type = params->bo_type; 154 + struct ttm_test_devices *priv = test->priv; 155 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 156 + struct ttm_operation_ctx ctx = { }; 157 + struct ttm_placement *placement; 158 + u32 mem_type = TTM_PL_VRAM; 159 + struct ttm_buffer_object *bo; 160 + struct ttm_place *place; 161 + int err; 162 + 163 + ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE); 164 + 165 + bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL); 166 + KUNIT_ASSERT_NOT_NULL(test, bo); 167 + 168 + place = ttm_place_kunit_init(test, mem_type, 0); 169 + placement = ttm_placement_kunit_init(test, place, 1); 170 + 171 + drm_gem_private_object_init(priv->drm, &bo->base, size); 172 + 173 + err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement, 174 + PAGE_SIZE, &ctx, NULL, NULL, 175 + &dummy_ttm_bo_destroy); 176 + dma_resv_unlock(bo->base.resv); 177 + 178 + KUNIT_EXPECT_EQ(test, err, 0); 179 + KUNIT_EXPECT_EQ(test, kref_read(&bo->kref), 1); 180 + KUNIT_EXPECT_PTR_EQ(test, bo->bdev, priv->ttm_dev); 181 + KUNIT_EXPECT_EQ(test, bo->type, bo_type); 182 + KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size); 183 + 184 + if (bo_type != ttm_bo_type_kernel) 185 + KUNIT_EXPECT_TRUE(test, 186 + drm_mm_node_allocated(&bo->base.vma_node.vm_node)); 187 + 188 + ttm_resource_free(bo, &bo->resource); 189 + ttm_bo_put(bo); 190 + ttm_mock_manager_fini(priv->ttm_dev, mem_type); 191 + } 192 + 193 + static void ttm_bo_init_reserved_resv(struct kunit *test) 194 + { 195 + enum ttm_bo_type bo_type = ttm_bo_type_device; 196 + struct ttm_test_devices *priv = test->priv; 197 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 198 + struct ttm_operation_ctx ctx = { }; 199 + struct ttm_placement *placement; 200 + struct ttm_buffer_object *bo; 201 + struct ttm_place *place; 202 + struct dma_resv resv; 203 + int err; 204 + 205 + bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL); 206 + KUNIT_ASSERT_NOT_NULL(test, bo); 207 + 208 + place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0); 209 + placement = ttm_placement_kunit_init(test, place, 1); 210 + 211 + drm_gem_private_object_init(priv->drm, &bo->base, size); 212 + dma_resv_init(&resv); 213 + dma_resv_lock(&resv, NULL); 214 + 215 + err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement, 216 + PAGE_SIZE, &ctx, NULL, &resv, 217 + &dummy_ttm_bo_destroy); 218 + dma_resv_unlock(bo->base.resv); 219 + 220 + KUNIT_EXPECT_EQ(test, err, 0); 221 + KUNIT_EXPECT_PTR_EQ(test, bo->base.resv, &resv); 222 + 223 + ttm_resource_free(bo, &bo->resource); 224 + ttm_bo_put(bo); 225 + } 226 + 227 + static void ttm_bo_validate_basic(struct kunit *test) 228 + { 229 + const struct ttm_bo_validate_test_case *params = test->param_value; 230 + u32 fst_mem = TTM_PL_SYSTEM, snd_mem = TTM_PL_VRAM; 231 + struct ttm_operation_ctx ctx_init = { }, ctx_val = { }; 232 + struct ttm_placement *fst_placement, *snd_placement; 233 + struct ttm_test_devices *priv = test->priv; 234 + struct ttm_place *fst_place, *snd_place; 235 + u32 size = ALIGN(SZ_8K, PAGE_SIZE); 236 + struct ttm_buffer_object *bo; 237 + int err; 238 + 239 + ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE); 240 + 241 + fst_place = ttm_place_kunit_init(test, fst_mem, 0); 242 + fst_placement = ttm_placement_kunit_init(test, fst_place, 1); 243 + 244 + bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL); 245 + KUNIT_ASSERT_NOT_NULL(test, bo); 246 + 247 + drm_gem_private_object_init(priv->drm, &bo->base, size); 248 + 249 + err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type, 250 + fst_placement, PAGE_SIZE, &ctx_init, NULL, 251 + NULL, &dummy_ttm_bo_destroy); 252 + KUNIT_EXPECT_EQ(test, err, 0); 253 + 254 + snd_place = ttm_place_kunit_init(test, snd_mem, DRM_BUDDY_TOPDOWN_ALLOCATION); 255 + snd_placement = ttm_placement_kunit_init(test, snd_place, 1); 256 + 257 + err = ttm_bo_validate(bo, snd_placement, &ctx_val); 258 + dma_resv_unlock(bo->base.resv); 259 + 260 + KUNIT_EXPECT_EQ(test, err, 0); 261 + KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, bo->base.size); 262 + KUNIT_EXPECT_NOT_NULL(test, bo->ttm); 263 + KUNIT_EXPECT_TRUE(test, ttm_tt_is_populated(bo->ttm)); 264 + KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem); 265 + KUNIT_EXPECT_EQ(test, bo->resource->placement, 266 + DRM_BUDDY_TOPDOWN_ALLOCATION); 267 + 268 + ttm_bo_put(bo); 269 + ttm_mock_manager_fini(priv->ttm_dev, snd_mem); 270 + } 271 + 272 + static void ttm_bo_validate_invalid_placement(struct kunit *test) 273 + { 274 + enum ttm_bo_type bo_type = ttm_bo_type_device; 275 + u32 unknown_mem_type = TTM_PL_PRIV + 1; 276 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 277 + struct ttm_operation_ctx ctx = { }; 278 + struct ttm_placement *placement; 279 + struct ttm_buffer_object *bo; 280 + struct ttm_place *place; 281 + int err; 282 + 283 + place = ttm_place_kunit_init(test, unknown_mem_type, 0); 284 + placement = ttm_placement_kunit_init(test, place, 1); 285 + 286 + bo = ttm_bo_kunit_init(test, test->priv, size, NULL); 287 + bo->type = bo_type; 288 + 289 + ttm_bo_reserve(bo, false, false, NULL); 290 + err = ttm_bo_validate(bo, placement, &ctx); 291 + dma_resv_unlock(bo->base.resv); 292 + 293 + KUNIT_EXPECT_EQ(test, err, -ENOMEM); 294 + 295 + ttm_bo_put(bo); 296 + } 297 + 298 + static void ttm_bo_validate_failed_alloc(struct kunit *test) 299 + { 300 + enum ttm_bo_type bo_type = ttm_bo_type_device; 301 + struct ttm_test_devices *priv = test->priv; 302 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 303 + struct ttm_operation_ctx ctx = { }; 304 + struct ttm_placement *placement; 305 + u32 mem_type = TTM_PL_VRAM; 306 + struct ttm_buffer_object *bo; 307 + struct ttm_place *place; 308 + int err; 309 + 310 + bo = ttm_bo_kunit_init(test, test->priv, size, NULL); 311 + bo->type = bo_type; 312 + 313 + ttm_bad_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE); 314 + 315 + place = ttm_place_kunit_init(test, mem_type, 0); 316 + placement = ttm_placement_kunit_init(test, place, 1); 317 + 318 + ttm_bo_reserve(bo, false, false, NULL); 319 + err = ttm_bo_validate(bo, placement, &ctx); 320 + dma_resv_unlock(bo->base.resv); 321 + 322 + KUNIT_EXPECT_EQ(test, err, -ENOMEM); 323 + 324 + ttm_bo_put(bo); 325 + ttm_bad_manager_fini(priv->ttm_dev, mem_type); 326 + } 327 + 328 + static void ttm_bo_validate_pinned(struct kunit *test) 329 + { 330 + enum ttm_bo_type bo_type = ttm_bo_type_device; 331 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 332 + struct ttm_operation_ctx ctx = { }; 333 + u32 mem_type = TTM_PL_SYSTEM; 334 + struct ttm_placement *placement; 335 + struct ttm_buffer_object *bo; 336 + struct ttm_place *place; 337 + int err; 338 + 339 + place = ttm_place_kunit_init(test, mem_type, 0); 340 + placement = ttm_placement_kunit_init(test, place, 1); 341 + 342 + bo = ttm_bo_kunit_init(test, test->priv, size, NULL); 343 + bo->type = bo_type; 344 + 345 + ttm_bo_reserve(bo, false, false, NULL); 346 + ttm_bo_pin(bo); 347 + err = ttm_bo_validate(bo, placement, &ctx); 348 + dma_resv_unlock(bo->base.resv); 349 + 350 + KUNIT_EXPECT_EQ(test, err, -EINVAL); 351 + 352 + ttm_bo_reserve(bo, false, false, NULL); 353 + ttm_bo_unpin(bo); 354 + dma_resv_unlock(bo->base.resv); 355 + 356 + ttm_bo_put(bo); 357 + } 358 + 359 + static const struct ttm_bo_validate_test_case ttm_mem_type_cases[] = { 360 + { 361 + .description = "System manager", 362 + .mem_type = TTM_PL_SYSTEM, 363 + }, 364 + { 365 + .description = "VRAM manager", 366 + .mem_type = TTM_PL_VRAM, 367 + }, 368 + }; 369 + 370 + KUNIT_ARRAY_PARAM(ttm_bo_validate_mem, ttm_mem_type_cases, 371 + ttm_bo_validate_case_desc); 372 + 373 + static void ttm_bo_validate_same_placement(struct kunit *test) 374 + { 375 + const struct ttm_bo_validate_test_case *params = test->param_value; 376 + struct ttm_operation_ctx ctx_init = { }, ctx_val = { }; 377 + struct ttm_test_devices *priv = test->priv; 378 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 379 + struct ttm_placement *placement; 380 + struct ttm_buffer_object *bo; 381 + struct ttm_place *place; 382 + int err; 383 + 384 + place = ttm_place_kunit_init(test, params->mem_type, 0); 385 + placement = ttm_placement_kunit_init(test, place, 1); 386 + 387 + if (params->mem_type != TTM_PL_SYSTEM) 388 + ttm_mock_manager_init(priv->ttm_dev, params->mem_type, MANAGER_SIZE); 389 + 390 + bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL); 391 + KUNIT_ASSERT_NOT_NULL(test, bo); 392 + 393 + drm_gem_private_object_init(priv->drm, &bo->base, size); 394 + 395 + err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type, 396 + placement, PAGE_SIZE, &ctx_init, NULL, 397 + NULL, &dummy_ttm_bo_destroy); 398 + KUNIT_EXPECT_EQ(test, err, 0); 399 + 400 + err = ttm_bo_validate(bo, placement, &ctx_val); 401 + dma_resv_unlock(bo->base.resv); 402 + 403 + KUNIT_EXPECT_EQ(test, err, 0); 404 + KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, 0); 405 + 406 + ttm_bo_put(bo); 407 + 408 + if (params->mem_type != TTM_PL_SYSTEM) 409 + ttm_mock_manager_fini(priv->ttm_dev, params->mem_type); 410 + } 411 + 412 + static void ttm_bo_validate_busy_placement(struct kunit *test) 413 + { 414 + u32 fst_mem = TTM_PL_VRAM, snd_mem = TTM_PL_VRAM + 1; 415 + struct ttm_operation_ctx ctx_init = { }, ctx_val = { }; 416 + struct ttm_placement *placement_init, *placement_val; 417 + enum ttm_bo_type bo_type = ttm_bo_type_device; 418 + struct ttm_test_devices *priv = test->priv; 419 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 420 + struct ttm_place *init_place, places[2]; 421 + struct ttm_resource_manager *man; 422 + struct ttm_buffer_object *bo; 423 + int err; 424 + 425 + ttm_bad_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE); 426 + ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE); 427 + 428 + init_place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0); 429 + placement_init = ttm_placement_kunit_init(test, init_place, 1); 430 + 431 + bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL); 432 + KUNIT_ASSERT_NOT_NULL(test, bo); 433 + 434 + drm_gem_private_object_init(priv->drm, &bo->base, size); 435 + 436 + err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement_init, 437 + PAGE_SIZE, &ctx_init, NULL, NULL, 438 + &dummy_ttm_bo_destroy); 439 + KUNIT_EXPECT_EQ(test, err, 0); 440 + 441 + places[0] = (struct ttm_place){ .mem_type = fst_mem, .flags = TTM_PL_FLAG_DESIRED }; 442 + places[1] = (struct ttm_place){ .mem_type = snd_mem, .flags = TTM_PL_FLAG_FALLBACK }; 443 + placement_val = ttm_placement_kunit_init(test, places, 2); 444 + 445 + err = ttm_bo_validate(bo, placement_val, &ctx_val); 446 + dma_resv_unlock(bo->base.resv); 447 + 448 + man = ttm_manager_type(priv->ttm_dev, snd_mem); 449 + 450 + KUNIT_EXPECT_EQ(test, err, 0); 451 + KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, bo->base.size); 452 + KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem); 453 + KUNIT_ASSERT_TRUE(test, list_is_singular(&man->lru[bo->priority])); 454 + 455 + ttm_bo_put(bo); 456 + ttm_bad_manager_fini(priv->ttm_dev, fst_mem); 457 + ttm_mock_manager_fini(priv->ttm_dev, snd_mem); 458 + } 459 + 460 + static void ttm_bo_validate_multihop(struct kunit *test) 461 + { 462 + const struct ttm_bo_validate_test_case *params = test->param_value; 463 + struct ttm_operation_ctx ctx_init = { }, ctx_val = { }; 464 + struct ttm_placement *placement_init, *placement_val; 465 + u32 fst_mem = TTM_PL_VRAM, tmp_mem = TTM_PL_TT, final_mem = TTM_PL_SYSTEM; 466 + struct ttm_test_devices *priv = test->priv; 467 + struct ttm_place *fst_place, *final_place; 468 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 469 + struct ttm_buffer_object *bo; 470 + int err; 471 + 472 + ttm_mock_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE); 473 + ttm_mock_manager_init(priv->ttm_dev, tmp_mem, MANAGER_SIZE); 474 + 475 + fst_place = ttm_place_kunit_init(test, fst_mem, 0); 476 + placement_init = ttm_placement_kunit_init(test, fst_place, 1); 477 + 478 + bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL); 479 + KUNIT_ASSERT_NOT_NULL(test, bo); 480 + 481 + drm_gem_private_object_init(priv->drm, &bo->base, size); 482 + 483 + err = ttm_bo_init_reserved(priv->ttm_dev, bo, params->bo_type, 484 + placement_init, PAGE_SIZE, &ctx_init, NULL, 485 + NULL, &dummy_ttm_bo_destroy); 486 + KUNIT_EXPECT_EQ(test, err, 0); 487 + 488 + final_place = ttm_place_kunit_init(test, final_mem, 0); 489 + placement_val = ttm_placement_kunit_init(test, final_place, 1); 490 + 491 + err = ttm_bo_validate(bo, placement_val, &ctx_val); 492 + dma_resv_unlock(bo->base.resv); 493 + 494 + KUNIT_EXPECT_EQ(test, err, 0); 495 + KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size * 2); 496 + KUNIT_EXPECT_EQ(test, bo->resource->mem_type, final_mem); 497 + 498 + ttm_bo_put(bo); 499 + 500 + ttm_mock_manager_fini(priv->ttm_dev, fst_mem); 501 + ttm_mock_manager_fini(priv->ttm_dev, tmp_mem); 502 + } 503 + 504 + static const struct ttm_bo_validate_test_case ttm_bo_no_placement_cases[] = { 505 + { 506 + .description = "Buffer object in system domain, no page vector", 507 + }, 508 + { 509 + .description = "Buffer object in system domain with an existing page vector", 510 + .with_ttm = true, 511 + }, 512 + }; 513 + 514 + KUNIT_ARRAY_PARAM(ttm_bo_no_placement, ttm_bo_no_placement_cases, 515 + ttm_bo_validate_case_desc); 516 + 517 + static void ttm_bo_validate_no_placement_signaled(struct kunit *test) 518 + { 519 + const struct ttm_bo_validate_test_case *params = test->param_value; 520 + enum ttm_bo_type bo_type = ttm_bo_type_device; 521 + struct ttm_test_devices *priv = test->priv; 522 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 523 + struct ttm_operation_ctx ctx = { }; 524 + u32 mem_type = TTM_PL_SYSTEM; 525 + struct ttm_resource_manager *man; 526 + struct ttm_placement *placement; 527 + struct ttm_buffer_object *bo; 528 + struct ttm_place *place; 529 + struct ttm_tt *old_tt; 530 + u32 flags; 531 + int err; 532 + 533 + place = ttm_place_kunit_init(test, mem_type, 0); 534 + man = ttm_manager_type(priv->ttm_dev, mem_type); 535 + 536 + bo = ttm_bo_kunit_init(test, test->priv, size, NULL); 537 + bo->type = bo_type; 538 + 539 + if (params->with_ttm) { 540 + old_tt = priv->ttm_dev->funcs->ttm_tt_create(bo, 0); 541 + ttm_pool_alloc(&priv->ttm_dev->pool, old_tt, &ctx); 542 + bo->ttm = old_tt; 543 + } 544 + 545 + err = ttm_resource_alloc(bo, place, &bo->resource); 546 + KUNIT_EXPECT_EQ(test, err, 0); 547 + KUNIT_ASSERT_EQ(test, man->usage, size); 548 + 549 + placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL); 550 + KUNIT_ASSERT_NOT_NULL(test, placement); 551 + 552 + ttm_bo_reserve(bo, false, false, NULL); 553 + err = ttm_bo_validate(bo, placement, &ctx); 554 + ttm_bo_unreserve(bo); 555 + 556 + KUNIT_EXPECT_EQ(test, err, 0); 557 + KUNIT_ASSERT_EQ(test, man->usage, 0); 558 + KUNIT_ASSERT_NOT_NULL(test, bo->ttm); 559 + KUNIT_EXPECT_EQ(test, ctx.bytes_moved, 0); 560 + 561 + if (params->with_ttm) { 562 + flags = bo->ttm->page_flags; 563 + 564 + KUNIT_ASSERT_PTR_EQ(test, bo->ttm, old_tt); 565 + KUNIT_ASSERT_FALSE(test, flags & TTM_TT_FLAG_PRIV_POPULATED); 566 + KUNIT_ASSERT_TRUE(test, flags & TTM_TT_FLAG_ZERO_ALLOC); 567 + } 568 + 569 + ttm_bo_put(bo); 570 + } 571 + 572 + static int threaded_dma_resv_signal(void *arg) 573 + { 574 + struct ttm_buffer_object *bo = arg; 575 + struct dma_resv *resv = bo->base.resv; 576 + struct dma_resv_iter cursor; 577 + struct dma_fence *fence; 578 + 579 + dma_resv_iter_begin(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP); 580 + dma_resv_for_each_fence_unlocked(&cursor, fence) { 581 + dma_fence_signal(fence); 582 + } 583 + dma_resv_iter_end(&cursor); 584 + 585 + return 0; 586 + } 587 + 588 + static void ttm_bo_validate_no_placement_not_signaled(struct kunit *test) 589 + { 590 + const struct ttm_bo_validate_test_case *params = test->param_value; 591 + enum dma_resv_usage usage = DMA_RESV_USAGE_BOOKKEEP; 592 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 593 + struct ttm_operation_ctx ctx = { }; 594 + u32 mem_type = TTM_PL_SYSTEM; 595 + struct ttm_placement *placement; 596 + struct ttm_buffer_object *bo; 597 + struct task_struct *task; 598 + struct ttm_place *place; 599 + int err; 600 + 601 + place = ttm_place_kunit_init(test, mem_type, 0); 602 + 603 + bo = ttm_bo_kunit_init(test, test->priv, size, NULL); 604 + bo->type = params->bo_type; 605 + 606 + err = ttm_resource_alloc(bo, place, &bo->resource); 607 + KUNIT_EXPECT_EQ(test, err, 0); 608 + 609 + placement = kunit_kzalloc(test, sizeof(*placement), GFP_KERNEL); 610 + KUNIT_ASSERT_NOT_NULL(test, placement); 611 + 612 + /* Create an active fence to simulate a non-idle resv object */ 613 + spin_lock_init(&fence_lock); 614 + dma_resv_kunit_active_fence_init(test, bo->base.resv, usage); 615 + 616 + task = kthread_create(threaded_dma_resv_signal, bo, "dma-resv-signal"); 617 + if (IS_ERR(task)) 618 + KUNIT_FAIL(test, "Couldn't create dma resv signal task\n"); 619 + 620 + wake_up_process(task); 621 + ttm_bo_reserve(bo, false, false, NULL); 622 + err = ttm_bo_validate(bo, placement, &ctx); 623 + ttm_bo_unreserve(bo); 624 + 625 + KUNIT_EXPECT_EQ(test, err, 0); 626 + KUNIT_ASSERT_NOT_NULL(test, bo->ttm); 627 + KUNIT_ASSERT_NULL(test, bo->resource); 628 + KUNIT_ASSERT_NULL(test, bo->bulk_move); 629 + KUNIT_EXPECT_EQ(test, ctx.bytes_moved, 0); 630 + 631 + if (bo->type != ttm_bo_type_sg) 632 + KUNIT_ASSERT_PTR_EQ(test, bo->base.resv, &bo->base._resv); 633 + 634 + /* Make sure we have an idle object at this point */ 635 + dma_resv_wait_timeout(bo->base.resv, usage, false, MAX_SCHEDULE_TIMEOUT); 636 + 637 + ttm_bo_put(bo); 638 + } 639 + 640 + static void ttm_bo_validate_move_fence_signaled(struct kunit *test) 641 + { 642 + enum ttm_bo_type bo_type = ttm_bo_type_device; 643 + struct ttm_test_devices *priv = test->priv; 644 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 645 + struct ttm_operation_ctx ctx = { }; 646 + u32 mem_type = TTM_PL_SYSTEM; 647 + struct ttm_resource_manager *man; 648 + struct ttm_placement *placement; 649 + struct ttm_buffer_object *bo; 650 + struct ttm_place *place; 651 + int err; 652 + 653 + man = ttm_manager_type(priv->ttm_dev, mem_type); 654 + man->move = dma_fence_get_stub(); 655 + 656 + bo = ttm_bo_kunit_init(test, test->priv, size, NULL); 657 + bo->type = bo_type; 658 + 659 + place = ttm_place_kunit_init(test, mem_type, 0); 660 + placement = ttm_placement_kunit_init(test, place, 1); 661 + 662 + ttm_bo_reserve(bo, false, false, NULL); 663 + err = ttm_bo_validate(bo, placement, &ctx); 664 + ttm_bo_unreserve(bo); 665 + 666 + KUNIT_EXPECT_EQ(test, err, 0); 667 + KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type); 668 + KUNIT_EXPECT_EQ(test, ctx.bytes_moved, size); 669 + 670 + ttm_bo_put(bo); 671 + dma_fence_put(man->move); 672 + } 673 + 674 + static const struct ttm_bo_validate_test_case ttm_bo_validate_wait_cases[] = { 675 + { 676 + .description = "Waits for GPU", 677 + .no_gpu_wait = false, 678 + }, 679 + { 680 + .description = "Tries to lock straight away", 681 + .no_gpu_wait = true, 682 + }, 683 + }; 684 + 685 + KUNIT_ARRAY_PARAM(ttm_bo_validate_wait, ttm_bo_validate_wait_cases, 686 + ttm_bo_validate_case_desc); 687 + 688 + static int threaded_fence_signal(void *arg) 689 + { 690 + struct dma_fence *fence = arg; 691 + 692 + msleep(20); 693 + 694 + return dma_fence_signal(fence); 695 + } 696 + 697 + static void ttm_bo_validate_move_fence_not_signaled(struct kunit *test) 698 + { 699 + const struct ttm_bo_validate_test_case *params = test->param_value; 700 + struct ttm_operation_ctx ctx_init = { }, 701 + ctx_val = { .no_wait_gpu = params->no_gpu_wait }; 702 + u32 fst_mem = TTM_PL_VRAM, snd_mem = TTM_PL_VRAM + 1; 703 + struct ttm_placement *placement_init, *placement_val; 704 + enum ttm_bo_type bo_type = ttm_bo_type_device; 705 + struct ttm_test_devices *priv = test->priv; 706 + u32 size = ALIGN(BO_SIZE, PAGE_SIZE); 707 + struct ttm_place *init_place, places[2]; 708 + struct ttm_resource_manager *man; 709 + struct ttm_buffer_object *bo; 710 + struct task_struct *task; 711 + int err; 712 + 713 + init_place = ttm_place_kunit_init(test, TTM_PL_SYSTEM, 0); 714 + placement_init = ttm_placement_kunit_init(test, init_place, 1); 715 + 716 + bo = kunit_kzalloc(test, sizeof(*bo), GFP_KERNEL); 717 + KUNIT_ASSERT_NOT_NULL(test, bo); 718 + 719 + drm_gem_private_object_init(priv->drm, &bo->base, size); 720 + 721 + err = ttm_bo_init_reserved(priv->ttm_dev, bo, bo_type, placement_init, 722 + PAGE_SIZE, &ctx_init, NULL, NULL, 723 + &dummy_ttm_bo_destroy); 724 + KUNIT_EXPECT_EQ(test, err, 0); 725 + 726 + ttm_mock_manager_init(priv->ttm_dev, fst_mem, MANAGER_SIZE); 727 + ttm_mock_manager_init(priv->ttm_dev, snd_mem, MANAGER_SIZE); 728 + 729 + places[0] = (struct ttm_place){ .mem_type = fst_mem, .flags = TTM_PL_FLAG_DESIRED }; 730 + places[1] = (struct ttm_place){ .mem_type = snd_mem, .flags = TTM_PL_FLAG_FALLBACK }; 731 + placement_val = ttm_placement_kunit_init(test, places, 2); 732 + 733 + spin_lock_init(&fence_lock); 734 + man = ttm_manager_type(priv->ttm_dev, fst_mem); 735 + man->move = alloc_mock_fence(test); 736 + 737 + task = kthread_create(threaded_fence_signal, man->move, "move-fence-signal"); 738 + if (IS_ERR(task)) 739 + KUNIT_FAIL(test, "Couldn't create move fence signal task\n"); 740 + 741 + wake_up_process(task); 742 + err = ttm_bo_validate(bo, placement_val, &ctx_val); 743 + dma_resv_unlock(bo->base.resv); 744 + 745 + dma_fence_wait_timeout(man->move, false, MAX_SCHEDULE_TIMEOUT); 746 + 747 + KUNIT_EXPECT_EQ(test, err, 0); 748 + KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size); 749 + 750 + if (params->no_gpu_wait) 751 + KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem); 752 + else 753 + KUNIT_EXPECT_EQ(test, bo->resource->mem_type, fst_mem); 754 + 755 + ttm_bo_put(bo); 756 + ttm_mock_manager_fini(priv->ttm_dev, fst_mem); 757 + ttm_mock_manager_fini(priv->ttm_dev, snd_mem); 758 + } 759 + 760 + static void ttm_bo_validate_swapout(struct kunit *test) 761 + { 762 + unsigned long size_big, size = ALIGN(BO_SIZE, PAGE_SIZE); 763 + enum ttm_bo_type bo_type = ttm_bo_type_device; 764 + struct ttm_buffer_object *bo_small, *bo_big; 765 + struct ttm_test_devices *priv = test->priv; 766 + struct ttm_operation_ctx ctx = { }; 767 + struct ttm_placement *placement; 768 + u32 mem_type = TTM_PL_TT; 769 + struct ttm_place *place; 770 + struct sysinfo si; 771 + int err; 772 + 773 + si_meminfo(&si); 774 + size_big = ALIGN(((u64)si.totalram * si.mem_unit / 2), PAGE_SIZE); 775 + 776 + ttm_mock_manager_init(priv->ttm_dev, mem_type, size_big + size); 777 + 778 + place = ttm_place_kunit_init(test, mem_type, 0); 779 + placement = ttm_placement_kunit_init(test, place, 1); 780 + 781 + bo_small = kunit_kzalloc(test, sizeof(*bo_small), GFP_KERNEL); 782 + KUNIT_ASSERT_NOT_NULL(test, bo_small); 783 + 784 + drm_gem_private_object_init(priv->drm, &bo_small->base, size); 785 + 786 + err = ttm_bo_init_reserved(priv->ttm_dev, bo_small, bo_type, placement, 787 + PAGE_SIZE, &ctx, NULL, NULL, 788 + &dummy_ttm_bo_destroy); 789 + KUNIT_EXPECT_EQ(test, err, 0); 790 + dma_resv_unlock(bo_small->base.resv); 791 + 792 + bo_big = ttm_bo_kunit_init(test, priv, size_big, NULL); 793 + 794 + dma_resv_lock(bo_big->base.resv, NULL); 795 + err = ttm_bo_validate(bo_big, placement, &ctx); 796 + dma_resv_unlock(bo_big->base.resv); 797 + 798 + KUNIT_EXPECT_EQ(test, err, 0); 799 + KUNIT_EXPECT_NOT_NULL(test, bo_big->resource); 800 + KUNIT_EXPECT_EQ(test, bo_big->resource->mem_type, mem_type); 801 + KUNIT_EXPECT_EQ(test, bo_small->resource->mem_type, TTM_PL_SYSTEM); 802 + KUNIT_EXPECT_TRUE(test, bo_small->ttm->page_flags & TTM_TT_FLAG_SWAPPED); 803 + 804 + ttm_bo_put(bo_big); 805 + ttm_bo_put(bo_small); 806 + 807 + ttm_mock_manager_fini(priv->ttm_dev, mem_type); 808 + } 809 + 810 + static void ttm_bo_validate_happy_evict(struct kunit *test) 811 + { 812 + u32 mem_type = TTM_PL_VRAM, mem_multihop = TTM_PL_TT, 813 + mem_type_evict = TTM_PL_SYSTEM; 814 + struct ttm_operation_ctx ctx_init = { }, ctx_val = { }; 815 + enum ttm_bo_type bo_type = ttm_bo_type_device; 816 + u32 small = SZ_8K, medium = SZ_512K, 817 + big = MANAGER_SIZE - (small + medium); 818 + u32 bo_sizes[] = { small, medium, big }; 819 + struct ttm_test_devices *priv = test->priv; 820 + struct ttm_buffer_object *bos, *bo_val; 821 + struct ttm_placement *placement; 822 + struct ttm_place *place; 823 + u32 bo_no = 3; 824 + int i, err; 825 + 826 + ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE); 827 + ttm_mock_manager_init(priv->ttm_dev, mem_multihop, MANAGER_SIZE); 828 + 829 + place = ttm_place_kunit_init(test, mem_type, 0); 830 + placement = ttm_placement_kunit_init(test, place, 1); 831 + 832 + bos = kunit_kmalloc_array(test, bo_no, sizeof(*bos), GFP_KERNEL); 833 + KUNIT_ASSERT_NOT_NULL(test, bos); 834 + 835 + memset(bos, 0, sizeof(*bos) * bo_no); 836 + for (i = 0; i < bo_no; i++) { 837 + drm_gem_private_object_init(priv->drm, &bos[i].base, bo_sizes[i]); 838 + err = ttm_bo_init_reserved(priv->ttm_dev, &bos[i], bo_type, placement, 839 + PAGE_SIZE, &ctx_init, NULL, NULL, 840 + &dummy_ttm_bo_destroy); 841 + dma_resv_unlock(bos[i].base.resv); 842 + } 843 + 844 + bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 845 + bo_val->type = bo_type; 846 + 847 + ttm_bo_reserve(bo_val, false, false, NULL); 848 + err = ttm_bo_validate(bo_val, placement, &ctx_val); 849 + ttm_bo_unreserve(bo_val); 850 + 851 + KUNIT_EXPECT_EQ(test, err, 0); 852 + KUNIT_EXPECT_EQ(test, bos[0].resource->mem_type, mem_type_evict); 853 + KUNIT_EXPECT_TRUE(test, bos[0].ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC); 854 + KUNIT_EXPECT_TRUE(test, bos[0].ttm->page_flags & TTM_TT_FLAG_PRIV_POPULATED); 855 + KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, small * 2 + BO_SIZE); 856 + KUNIT_EXPECT_EQ(test, bos[1].resource->mem_type, mem_type); 857 + 858 + for (i = 0; i < bo_no; i++) 859 + ttm_bo_put(&bos[i]); 860 + ttm_bo_put(bo_val); 861 + 862 + ttm_mock_manager_fini(priv->ttm_dev, mem_type); 863 + ttm_mock_manager_fini(priv->ttm_dev, mem_multihop); 864 + } 865 + 866 + static void ttm_bo_validate_all_pinned_evict(struct kunit *test) 867 + { 868 + struct ttm_operation_ctx ctx_init = { }, ctx_val = { }; 869 + enum ttm_bo_type bo_type = ttm_bo_type_device; 870 + struct ttm_buffer_object *bo_big, *bo_small; 871 + struct ttm_test_devices *priv = test->priv; 872 + struct ttm_placement *placement; 873 + u32 mem_type = TTM_PL_VRAM, mem_multihop = TTM_PL_TT; 874 + struct ttm_place *place; 875 + int err; 876 + 877 + ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE); 878 + ttm_mock_manager_init(priv->ttm_dev, mem_multihop, MANAGER_SIZE); 879 + 880 + place = ttm_place_kunit_init(test, mem_type, 0); 881 + placement = ttm_placement_kunit_init(test, place, 1); 882 + 883 + bo_big = kunit_kzalloc(test, sizeof(*bo_big), GFP_KERNEL); 884 + KUNIT_ASSERT_NOT_NULL(test, bo_big); 885 + 886 + drm_gem_private_object_init(priv->drm, &bo_big->base, MANAGER_SIZE); 887 + err = ttm_bo_init_reserved(priv->ttm_dev, bo_big, bo_type, placement, 888 + PAGE_SIZE, &ctx_init, NULL, NULL, 889 + &dummy_ttm_bo_destroy); 890 + KUNIT_EXPECT_EQ(test, err, 0); 891 + 892 + ttm_bo_pin(bo_big); 893 + dma_resv_unlock(bo_big->base.resv); 894 + 895 + bo_small = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 896 + bo_small->type = bo_type; 897 + 898 + ttm_bo_reserve(bo_small, false, false, NULL); 899 + err = ttm_bo_validate(bo_small, placement, &ctx_val); 900 + ttm_bo_unreserve(bo_small); 901 + 902 + KUNIT_EXPECT_EQ(test, err, -ENOMEM); 903 + 904 + ttm_bo_put(bo_small); 905 + 906 + ttm_bo_reserve(bo_big, false, false, NULL); 907 + ttm_bo_unpin(bo_big); 908 + dma_resv_unlock(bo_big->base.resv); 909 + ttm_bo_put(bo_big); 910 + 911 + ttm_mock_manager_fini(priv->ttm_dev, mem_type); 912 + ttm_mock_manager_fini(priv->ttm_dev, mem_multihop); 913 + } 914 + 915 + static void ttm_bo_validate_allowed_only_evict(struct kunit *test) 916 + { 917 + u32 mem_type = TTM_PL_VRAM, mem_multihop = TTM_PL_TT, 918 + mem_type_evict = TTM_PL_SYSTEM; 919 + struct ttm_buffer_object *bo, *bo_evictable, *bo_pinned; 920 + struct ttm_operation_ctx ctx_init = { }, ctx_val = { }; 921 + enum ttm_bo_type bo_type = ttm_bo_type_device; 922 + struct ttm_test_devices *priv = test->priv; 923 + struct ttm_placement *placement; 924 + struct ttm_place *place; 925 + u32 size = SZ_512K; 926 + int err; 927 + 928 + ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE); 929 + ttm_mock_manager_init(priv->ttm_dev, mem_multihop, MANAGER_SIZE); 930 + 931 + place = ttm_place_kunit_init(test, mem_type, 0); 932 + placement = ttm_placement_kunit_init(test, place, 1); 933 + 934 + bo_pinned = kunit_kzalloc(test, sizeof(*bo_pinned), GFP_KERNEL); 935 + KUNIT_ASSERT_NOT_NULL(test, bo_pinned); 936 + 937 + drm_gem_private_object_init(priv->drm, &bo_pinned->base, size); 938 + err = ttm_bo_init_reserved(priv->ttm_dev, bo_pinned, bo_type, placement, 939 + PAGE_SIZE, &ctx_init, NULL, NULL, 940 + &dummy_ttm_bo_destroy); 941 + KUNIT_EXPECT_EQ(test, err, 0); 942 + ttm_bo_pin(bo_pinned); 943 + dma_resv_unlock(bo_pinned->base.resv); 944 + 945 + bo_evictable = kunit_kzalloc(test, sizeof(*bo_evictable), GFP_KERNEL); 946 + KUNIT_ASSERT_NOT_NULL(test, bo_evictable); 947 + 948 + drm_gem_private_object_init(priv->drm, &bo_evictable->base, size); 949 + err = ttm_bo_init_reserved(priv->ttm_dev, bo_evictable, bo_type, placement, 950 + PAGE_SIZE, &ctx_init, NULL, NULL, 951 + &dummy_ttm_bo_destroy); 952 + KUNIT_EXPECT_EQ(test, err, 0); 953 + dma_resv_unlock(bo_evictable->base.resv); 954 + 955 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 956 + bo->type = bo_type; 957 + 958 + ttm_bo_reserve(bo, false, false, NULL); 959 + err = ttm_bo_validate(bo, placement, &ctx_val); 960 + ttm_bo_unreserve(bo); 961 + 962 + KUNIT_EXPECT_EQ(test, err, 0); 963 + KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type); 964 + KUNIT_EXPECT_EQ(test, bo_pinned->resource->mem_type, mem_type); 965 + KUNIT_EXPECT_EQ(test, bo_evictable->resource->mem_type, mem_type_evict); 966 + KUNIT_EXPECT_EQ(test, ctx_val.bytes_moved, size * 2 + BO_SIZE); 967 + 968 + ttm_bo_put(bo); 969 + ttm_bo_put(bo_evictable); 970 + 971 + ttm_bo_reserve(bo_pinned, false, false, NULL); 972 + ttm_bo_unpin(bo_pinned); 973 + dma_resv_unlock(bo_pinned->base.resv); 974 + ttm_bo_put(bo_pinned); 975 + 976 + ttm_mock_manager_fini(priv->ttm_dev, mem_type); 977 + ttm_mock_manager_fini(priv->ttm_dev, mem_multihop); 978 + } 979 + 980 + static void ttm_bo_validate_deleted_evict(struct kunit *test) 981 + { 982 + struct ttm_operation_ctx ctx_init = { }, ctx_val = { }; 983 + u32 small = SZ_8K, big = MANAGER_SIZE - BO_SIZE; 984 + enum ttm_bo_type bo_type = ttm_bo_type_device; 985 + struct ttm_buffer_object *bo_big, *bo_small; 986 + struct ttm_test_devices *priv = test->priv; 987 + struct ttm_resource_manager *man; 988 + u32 mem_type = TTM_PL_VRAM; 989 + struct ttm_placement *placement; 990 + struct ttm_place *place; 991 + int err; 992 + 993 + ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE); 994 + man = ttm_manager_type(priv->ttm_dev, mem_type); 995 + 996 + place = ttm_place_kunit_init(test, mem_type, 0); 997 + placement = ttm_placement_kunit_init(test, place, 1); 998 + 999 + bo_big = kunit_kzalloc(test, sizeof(*bo_big), GFP_KERNEL); 1000 + KUNIT_ASSERT_NOT_NULL(test, bo_big); 1001 + 1002 + drm_gem_private_object_init(priv->drm, &bo_big->base, big); 1003 + err = ttm_bo_init_reserved(priv->ttm_dev, bo_big, bo_type, placement, 1004 + PAGE_SIZE, &ctx_init, NULL, NULL, 1005 + &dummy_ttm_bo_destroy); 1006 + KUNIT_EXPECT_EQ(test, err, 0); 1007 + KUNIT_EXPECT_EQ(test, ttm_resource_manager_usage(man), big); 1008 + 1009 + dma_resv_unlock(bo_big->base.resv); 1010 + bo_big->deleted = true; 1011 + 1012 + bo_small = ttm_bo_kunit_init(test, test->priv, small, NULL); 1013 + bo_small->type = bo_type; 1014 + 1015 + ttm_bo_reserve(bo_small, false, false, NULL); 1016 + err = ttm_bo_validate(bo_small, placement, &ctx_val); 1017 + ttm_bo_unreserve(bo_small); 1018 + 1019 + KUNIT_EXPECT_EQ(test, err, 0); 1020 + KUNIT_EXPECT_EQ(test, bo_small->resource->mem_type, mem_type); 1021 + KUNIT_EXPECT_EQ(test, ttm_resource_manager_usage(man), small); 1022 + KUNIT_EXPECT_NULL(test, bo_big->ttm); 1023 + KUNIT_EXPECT_NULL(test, bo_big->resource); 1024 + 1025 + ttm_bo_put(bo_small); 1026 + ttm_bo_put(bo_big); 1027 + ttm_mock_manager_fini(priv->ttm_dev, mem_type); 1028 + } 1029 + 1030 + static void ttm_bo_validate_busy_domain_evict(struct kunit *test) 1031 + { 1032 + u32 mem_type = TTM_PL_VRAM, mem_type_evict = TTM_PL_MOCK1; 1033 + struct ttm_operation_ctx ctx_init = { }, ctx_val = { }; 1034 + enum ttm_bo_type bo_type = ttm_bo_type_device; 1035 + struct ttm_test_devices *priv = test->priv; 1036 + struct ttm_buffer_object *bo_init, *bo_val; 1037 + struct ttm_placement *placement; 1038 + struct ttm_place *place; 1039 + int err; 1040 + 1041 + /* 1042 + * Drop the default device and setup a new one that points to busy 1043 + * thus unsuitable eviction domain 1044 + */ 1045 + ttm_device_fini(priv->ttm_dev); 1046 + 1047 + err = ttm_device_kunit_init_bad_evict(test->priv, priv->ttm_dev, false, false); 1048 + KUNIT_ASSERT_EQ(test, err, 0); 1049 + 1050 + ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE); 1051 + ttm_busy_manager_init(priv->ttm_dev, mem_type_evict, MANAGER_SIZE); 1052 + 1053 + place = ttm_place_kunit_init(test, mem_type, 0); 1054 + placement = ttm_placement_kunit_init(test, place, 1); 1055 + 1056 + bo_init = kunit_kzalloc(test, sizeof(*bo_init), GFP_KERNEL); 1057 + KUNIT_ASSERT_NOT_NULL(test, bo_init); 1058 + 1059 + drm_gem_private_object_init(priv->drm, &bo_init->base, MANAGER_SIZE); 1060 + err = ttm_bo_init_reserved(priv->ttm_dev, bo_init, bo_type, placement, 1061 + PAGE_SIZE, &ctx_init, NULL, NULL, 1062 + &dummy_ttm_bo_destroy); 1063 + KUNIT_EXPECT_EQ(test, err, 0); 1064 + dma_resv_unlock(bo_init->base.resv); 1065 + 1066 + bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 1067 + bo_val->type = bo_type; 1068 + 1069 + ttm_bo_reserve(bo_val, false, false, NULL); 1070 + err = ttm_bo_validate(bo_val, placement, &ctx_val); 1071 + ttm_bo_unreserve(bo_val); 1072 + 1073 + KUNIT_EXPECT_EQ(test, err, -ENOMEM); 1074 + KUNIT_EXPECT_EQ(test, bo_init->resource->mem_type, mem_type); 1075 + KUNIT_EXPECT_NULL(test, bo_val->resource); 1076 + 1077 + ttm_bo_put(bo_init); 1078 + ttm_bo_put(bo_val); 1079 + 1080 + ttm_mock_manager_fini(priv->ttm_dev, mem_type); 1081 + ttm_bad_manager_fini(priv->ttm_dev, mem_type_evict); 1082 + } 1083 + 1084 + static void ttm_bo_validate_evict_gutting(struct kunit *test) 1085 + { 1086 + struct ttm_operation_ctx ctx_init = { }, ctx_val = { }; 1087 + enum ttm_bo_type bo_type = ttm_bo_type_device; 1088 + struct ttm_test_devices *priv = test->priv; 1089 + struct ttm_buffer_object *bo, *bo_evict; 1090 + u32 mem_type = TTM_PL_MOCK1; 1091 + struct ttm_placement *placement; 1092 + struct ttm_place *place; 1093 + int err; 1094 + 1095 + ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE); 1096 + 1097 + place = ttm_place_kunit_init(test, mem_type, 0); 1098 + placement = ttm_placement_kunit_init(test, place, 1); 1099 + 1100 + bo_evict = kunit_kzalloc(test, sizeof(*bo_evict), GFP_KERNEL); 1101 + KUNIT_ASSERT_NOT_NULL(test, bo_evict); 1102 + 1103 + drm_gem_private_object_init(priv->drm, &bo_evict->base, MANAGER_SIZE); 1104 + err = ttm_bo_init_reserved(priv->ttm_dev, bo_evict, bo_type, placement, 1105 + PAGE_SIZE, &ctx_init, NULL, NULL, 1106 + &dummy_ttm_bo_destroy); 1107 + KUNIT_EXPECT_EQ(test, err, 0); 1108 + dma_resv_unlock(bo_evict->base.resv); 1109 + 1110 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 1111 + bo->type = bo_type; 1112 + 1113 + ttm_bo_reserve(bo, false, false, NULL); 1114 + err = ttm_bo_validate(bo, placement, &ctx_val); 1115 + ttm_bo_unreserve(bo); 1116 + 1117 + KUNIT_EXPECT_EQ(test, err, 0); 1118 + KUNIT_EXPECT_EQ(test, bo->resource->mem_type, mem_type); 1119 + KUNIT_ASSERT_NULL(test, bo_evict->resource); 1120 + KUNIT_ASSERT_TRUE(test, bo_evict->ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC); 1121 + 1122 + ttm_bo_put(bo_evict); 1123 + ttm_bo_put(bo); 1124 + 1125 + ttm_mock_manager_fini(priv->ttm_dev, mem_type); 1126 + } 1127 + 1128 + static void ttm_bo_validate_recrusive_evict(struct kunit *test) 1129 + { 1130 + u32 mem_type = TTM_PL_TT, mem_type_evict = TTM_PL_MOCK2; 1131 + struct ttm_operation_ctx ctx_init = { }, ctx_val = { }; 1132 + struct ttm_placement *placement_tt, *placement_mock; 1133 + struct ttm_buffer_object *bo_tt, *bo_mock, *bo_val; 1134 + enum ttm_bo_type bo_type = ttm_bo_type_device; 1135 + struct ttm_test_devices *priv = test->priv; 1136 + struct ttm_place *place_tt, *place_mock; 1137 + int err; 1138 + 1139 + ttm_mock_manager_init(priv->ttm_dev, mem_type, MANAGER_SIZE); 1140 + ttm_mock_manager_init(priv->ttm_dev, mem_type_evict, MANAGER_SIZE); 1141 + 1142 + place_tt = ttm_place_kunit_init(test, mem_type, 0); 1143 + place_mock = ttm_place_kunit_init(test, mem_type_evict, 0); 1144 + 1145 + placement_tt = ttm_placement_kunit_init(test, place_tt, 1); 1146 + placement_mock = ttm_placement_kunit_init(test, place_mock, 1); 1147 + 1148 + bo_tt = kunit_kzalloc(test, sizeof(*bo_tt), GFP_KERNEL); 1149 + KUNIT_ASSERT_NOT_NULL(test, bo_tt); 1150 + 1151 + bo_mock = kunit_kzalloc(test, sizeof(*bo_mock), GFP_KERNEL); 1152 + KUNIT_ASSERT_NOT_NULL(test, bo_mock); 1153 + 1154 + drm_gem_private_object_init(priv->drm, &bo_tt->base, MANAGER_SIZE); 1155 + err = ttm_bo_init_reserved(priv->ttm_dev, bo_tt, bo_type, placement_tt, 1156 + PAGE_SIZE, &ctx_init, NULL, NULL, 1157 + &dummy_ttm_bo_destroy); 1158 + KUNIT_EXPECT_EQ(test, err, 0); 1159 + dma_resv_unlock(bo_tt->base.resv); 1160 + 1161 + drm_gem_private_object_init(priv->drm, &bo_mock->base, MANAGER_SIZE); 1162 + err = ttm_bo_init_reserved(priv->ttm_dev, bo_mock, bo_type, placement_mock, 1163 + PAGE_SIZE, &ctx_init, NULL, NULL, 1164 + &dummy_ttm_bo_destroy); 1165 + KUNIT_EXPECT_EQ(test, err, 0); 1166 + dma_resv_unlock(bo_mock->base.resv); 1167 + 1168 + bo_val = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 1169 + bo_val->type = bo_type; 1170 + 1171 + ttm_bo_reserve(bo_val, false, false, NULL); 1172 + err = ttm_bo_validate(bo_val, placement_tt, &ctx_val); 1173 + ttm_bo_unreserve(bo_val); 1174 + 1175 + KUNIT_EXPECT_EQ(test, err, 0); 1176 + 1177 + ttm_mock_manager_fini(priv->ttm_dev, mem_type); 1178 + ttm_mock_manager_fini(priv->ttm_dev, mem_type_evict); 1179 + 1180 + ttm_bo_put(bo_val); 1181 + ttm_bo_put(bo_tt); 1182 + ttm_bo_put(bo_mock); 1183 + } 1184 + 1185 + static struct kunit_case ttm_bo_validate_test_cases[] = { 1186 + KUNIT_CASE_PARAM(ttm_bo_init_reserved_sys_man, ttm_bo_types_gen_params), 1187 + KUNIT_CASE_PARAM(ttm_bo_init_reserved_mock_man, ttm_bo_types_gen_params), 1188 + KUNIT_CASE(ttm_bo_init_reserved_resv), 1189 + KUNIT_CASE_PARAM(ttm_bo_validate_basic, ttm_bo_types_gen_params), 1190 + KUNIT_CASE(ttm_bo_validate_invalid_placement), 1191 + KUNIT_CASE_PARAM(ttm_bo_validate_same_placement, 1192 + ttm_bo_validate_mem_gen_params), 1193 + KUNIT_CASE(ttm_bo_validate_failed_alloc), 1194 + KUNIT_CASE(ttm_bo_validate_pinned), 1195 + KUNIT_CASE(ttm_bo_validate_busy_placement), 1196 + KUNIT_CASE_PARAM(ttm_bo_validate_multihop, ttm_bo_types_gen_params), 1197 + KUNIT_CASE_PARAM(ttm_bo_validate_no_placement_signaled, 1198 + ttm_bo_no_placement_gen_params), 1199 + KUNIT_CASE_PARAM(ttm_bo_validate_no_placement_not_signaled, 1200 + ttm_bo_types_gen_params), 1201 + KUNIT_CASE(ttm_bo_validate_move_fence_signaled), 1202 + KUNIT_CASE_PARAM(ttm_bo_validate_move_fence_not_signaled, 1203 + ttm_bo_validate_wait_gen_params), 1204 + KUNIT_CASE(ttm_bo_validate_swapout), 1205 + KUNIT_CASE(ttm_bo_validate_happy_evict), 1206 + KUNIT_CASE(ttm_bo_validate_all_pinned_evict), 1207 + KUNIT_CASE(ttm_bo_validate_allowed_only_evict), 1208 + KUNIT_CASE(ttm_bo_validate_deleted_evict), 1209 + KUNIT_CASE(ttm_bo_validate_busy_domain_evict), 1210 + KUNIT_CASE(ttm_bo_validate_evict_gutting), 1211 + KUNIT_CASE(ttm_bo_validate_recrusive_evict), 1212 + {} 1213 + }; 1214 + 1215 + static struct kunit_suite ttm_bo_validate_test_suite = { 1216 + .name = "ttm_bo_validate", 1217 + .init = ttm_test_devices_all_init, 1218 + .exit = ttm_test_devices_fini, 1219 + .test_cases = ttm_bo_validate_test_cases, 1220 + }; 1221 + 1222 + kunit_test_suites(&ttm_bo_validate_test_suite); 1223 + 1224 + MODULE_DESCRIPTION("KUnit tests for ttm_bo APIs"); 1225 + MODULE_LICENSE("GPL and additional rights");
+2 -1
drivers/gpu/drm/ttm/tests/ttm_device_test.c
··· 209 209 210 210 kunit_test_suites(&ttm_device_test_suite); 211 211 212 - MODULE_LICENSE("GPL"); 212 + MODULE_DESCRIPTION("KUnit tests for ttm_device APIs"); 213 + MODULE_LICENSE("GPL and additional rights");
+162 -16
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c
··· 6 6 7 7 #include "ttm_kunit_helpers.h" 8 8 9 - static struct ttm_tt *ttm_tt_simple_create(struct ttm_buffer_object *bo, 10 - uint32_t page_flags) 9 + static const struct ttm_place sys_place = { 10 + .fpfn = 0, 11 + .lpfn = 0, 12 + .mem_type = TTM_PL_SYSTEM, 13 + .flags = TTM_PL_FLAG_FALLBACK, 14 + }; 15 + 16 + static const struct ttm_place mock1_place = { 17 + .fpfn = 0, 18 + .lpfn = 0, 19 + .mem_type = TTM_PL_MOCK1, 20 + .flags = TTM_PL_FLAG_FALLBACK, 21 + }; 22 + 23 + static const struct ttm_place mock2_place = { 24 + .fpfn = 0, 25 + .lpfn = 0, 26 + .mem_type = TTM_PL_MOCK2, 27 + .flags = TTM_PL_FLAG_FALLBACK, 28 + }; 29 + 30 + static struct ttm_placement sys_placement = { 31 + .num_placement = 1, 32 + .placement = &sys_place, 33 + }; 34 + 35 + static struct ttm_placement bad_placement = { 36 + .num_placement = 1, 37 + .placement = &mock1_place, 38 + }; 39 + 40 + static struct ttm_placement mock_placement = { 41 + .num_placement = 1, 42 + .placement = &mock2_place, 43 + }; 44 + 45 + static struct ttm_tt *ttm_tt_simple_create(struct ttm_buffer_object *bo, u32 page_flags) 11 46 { 12 47 struct ttm_tt *tt; 13 48 ··· 57 22 kfree(ttm); 58 23 } 59 24 60 - static void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo) 25 + static int mock_move(struct ttm_buffer_object *bo, bool evict, 26 + struct ttm_operation_ctx *ctx, 27 + struct ttm_resource *new_mem, 28 + struct ttm_place *hop) 61 29 { 30 + struct ttm_resource *old_mem = bo->resource; 31 + 32 + if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm)) { 33 + ttm_bo_move_null(bo, new_mem); 34 + return 0; 35 + } 36 + 37 + if (bo->resource->mem_type == TTM_PL_VRAM && 38 + new_mem->mem_type == TTM_PL_SYSTEM) { 39 + hop->mem_type = TTM_PL_TT; 40 + hop->flags = TTM_PL_FLAG_TEMPORARY; 41 + hop->fpfn = 0; 42 + hop->lpfn = 0; 43 + return -EMULTIHOP; 44 + } 45 + 46 + if ((old_mem->mem_type == TTM_PL_SYSTEM && 47 + new_mem->mem_type == TTM_PL_TT) || 48 + (old_mem->mem_type == TTM_PL_TT && 49 + new_mem->mem_type == TTM_PL_SYSTEM)) { 50 + ttm_bo_move_null(bo, new_mem); 51 + return 0; 52 + } 53 + 54 + return ttm_bo_move_memcpy(bo, ctx, new_mem); 55 + } 56 + 57 + static void mock_evict_flags(struct ttm_buffer_object *bo, 58 + struct ttm_placement *placement) 59 + { 60 + switch (bo->resource->mem_type) { 61 + case TTM_PL_VRAM: 62 + case TTM_PL_SYSTEM: 63 + *placement = sys_placement; 64 + break; 65 + case TTM_PL_TT: 66 + *placement = mock_placement; 67 + break; 68 + case TTM_PL_MOCK1: 69 + /* Purge objects coming from this domain */ 70 + break; 71 + } 72 + } 73 + 74 + static void bad_evict_flags(struct ttm_buffer_object *bo, 75 + struct ttm_placement *placement) 76 + { 77 + *placement = bad_placement; 78 + } 79 + 80 + static int ttm_device_kunit_init_with_funcs(struct ttm_test_devices *priv, 81 + struct ttm_device *ttm, 82 + bool use_dma_alloc, 83 + bool use_dma32, 84 + struct ttm_device_funcs *funcs) 85 + { 86 + struct drm_device *drm = priv->drm; 87 + int err; 88 + 89 + err = ttm_device_init(ttm, funcs, drm->dev, 90 + drm->anon_inode->i_mapping, 91 + drm->vma_offset_manager, 92 + use_dma_alloc, use_dma32); 93 + 94 + return err; 62 95 } 63 96 64 97 struct ttm_device_funcs ttm_dev_funcs = { 65 98 .ttm_tt_create = ttm_tt_simple_create, 66 99 .ttm_tt_destroy = ttm_tt_simple_destroy, 100 + .move = mock_move, 101 + .eviction_valuable = ttm_bo_eviction_valuable, 102 + .evict_flags = mock_evict_flags, 67 103 }; 68 104 EXPORT_SYMBOL_GPL(ttm_dev_funcs); 69 105 ··· 143 37 bool use_dma_alloc, 144 38 bool use_dma32) 145 39 { 146 - struct drm_device *drm = priv->drm; 147 - int err; 148 - 149 - err = ttm_device_init(ttm, &ttm_dev_funcs, drm->dev, 150 - drm->anon_inode->i_mapping, 151 - drm->vma_offset_manager, 152 - use_dma_alloc, use_dma32); 153 - 154 - return err; 40 + return ttm_device_kunit_init_with_funcs(priv, ttm, use_dma_alloc, 41 + use_dma32, &ttm_dev_funcs); 155 42 } 156 43 EXPORT_SYMBOL_GPL(ttm_device_kunit_init); 157 44 45 + struct ttm_device_funcs ttm_dev_funcs_bad_evict = { 46 + .ttm_tt_create = ttm_tt_simple_create, 47 + .ttm_tt_destroy = ttm_tt_simple_destroy, 48 + .move = mock_move, 49 + .eviction_valuable = ttm_bo_eviction_valuable, 50 + .evict_flags = bad_evict_flags, 51 + }; 52 + EXPORT_SYMBOL_GPL(ttm_dev_funcs_bad_evict); 53 + 54 + int ttm_device_kunit_init_bad_evict(struct ttm_test_devices *priv, 55 + struct ttm_device *ttm, 56 + bool use_dma_alloc, 57 + bool use_dma32) 58 + { 59 + return ttm_device_kunit_init_with_funcs(priv, ttm, use_dma_alloc, 60 + use_dma32, &ttm_dev_funcs_bad_evict); 61 + } 62 + EXPORT_SYMBOL_GPL(ttm_device_kunit_init_bad_evict); 63 + 158 64 struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test, 159 65 struct ttm_test_devices *devs, 160 - size_t size) 66 + size_t size, 67 + struct dma_resv *obj) 161 68 { 162 69 struct drm_gem_object gem_obj = { }; 163 70 struct ttm_buffer_object *bo; ··· 180 61 KUNIT_ASSERT_NOT_NULL(test, bo); 181 62 182 63 bo->base = gem_obj; 64 + 65 + if (obj) 66 + bo->base.resv = obj; 67 + 183 68 err = drm_gem_object_init(devs->drm, &bo->base, size); 184 69 KUNIT_ASSERT_EQ(test, err, 0); 185 70 ··· 196 73 } 197 74 EXPORT_SYMBOL_GPL(ttm_bo_kunit_init); 198 75 199 - struct ttm_place *ttm_place_kunit_init(struct kunit *test, 200 - uint32_t mem_type, uint32_t flags) 76 + struct ttm_place *ttm_place_kunit_init(struct kunit *test, u32 mem_type, u32 flags) 201 77 { 202 78 struct ttm_place *place; 203 79 ··· 210 88 } 211 89 EXPORT_SYMBOL_GPL(ttm_place_kunit_init); 212 90 91 + void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo) 92 + { 93 + drm_gem_object_release(&bo->base); 94 + } 95 + EXPORT_SYMBOL_GPL(dummy_ttm_bo_destroy); 96 + 213 97 struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test) 214 98 { 215 99 struct ttm_test_devices *devs; ··· 225 97 226 98 devs->dev = drm_kunit_helper_alloc_device(test); 227 99 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, devs->dev); 100 + 101 + /* Set mask for alloc_coherent mappings to enable ttm_pool_alloc testing */ 102 + devs->dev->coherent_dma_mask = -1; 228 103 229 104 devs->drm = __drm_kunit_helper_alloc_drm_device(test, devs->dev, 230 105 sizeof(*devs->drm), 0, ··· 281 150 } 282 151 EXPORT_SYMBOL_GPL(ttm_test_devices_init); 283 152 153 + int ttm_test_devices_all_init(struct kunit *test) 154 + { 155 + struct ttm_test_devices *priv; 156 + 157 + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); 158 + KUNIT_ASSERT_NOT_NULL(test, priv); 159 + 160 + priv = ttm_test_devices_all(test); 161 + test->priv = priv; 162 + 163 + return 0; 164 + } 165 + EXPORT_SYMBOL_GPL(ttm_test_devices_all_init); 166 + 284 167 void ttm_test_devices_fini(struct kunit *test) 285 168 { 286 169 ttm_test_devices_put(test, test->priv); 287 170 } 288 171 EXPORT_SYMBOL_GPL(ttm_test_devices_fini); 289 172 290 - MODULE_LICENSE("GPL"); 173 + MODULE_DESCRIPTION("TTM KUnit test helper functions"); 174 + MODULE_LICENSE("GPL and additional rights");
+14 -3
drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.h
··· 13 13 #include <drm/drm_kunit_helpers.h> 14 14 #include <kunit/test.h> 15 15 16 + #define TTM_PL_MOCK1 (TTM_PL_PRIV + 1) 17 + #define TTM_PL_MOCK2 (TTM_PL_PRIV + 2) 18 + 16 19 extern struct ttm_device_funcs ttm_dev_funcs; 20 + extern struct ttm_device_funcs ttm_dev_funcs_bad_evict; 17 21 18 22 struct ttm_test_devices { 19 23 struct drm_device *drm; ··· 30 26 struct ttm_device *ttm, 31 27 bool use_dma_alloc, 32 28 bool use_dma32); 29 + int ttm_device_kunit_init_bad_evict(struct ttm_test_devices *priv, 30 + struct ttm_device *ttm, 31 + bool use_dma_alloc, 32 + bool use_dma32); 33 33 struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test, 34 34 struct ttm_test_devices *devs, 35 - size_t size); 36 - struct ttm_place *ttm_place_kunit_init(struct kunit *test, 37 - uint32_t mem_type, uint32_t flags); 35 + size_t size, 36 + struct dma_resv *obj); 37 + struct ttm_place *ttm_place_kunit_init(struct kunit *test, u32 mem_type, 38 + u32 flags); 39 + void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo); 38 40 39 41 struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test); 40 42 struct ttm_test_devices *ttm_test_devices_all(struct kunit *test); ··· 49 39 50 40 /* Generic init/fini for tests that only need DRM/TTM devices */ 51 41 int ttm_test_devices_init(struct kunit *test); 42 + int ttm_test_devices_all_init(struct kunit *test); 52 43 void ttm_test_devices_fini(struct kunit *test); 53 44 54 45 #endif // TTM_KUNIT_HELPERS_H
+234
drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 AND MIT 2 + /* 3 + * Copyright © 2023 Intel Corporation 4 + */ 5 + #include <drm/ttm/ttm_resource.h> 6 + #include <drm/ttm/ttm_device.h> 7 + #include <drm/ttm/ttm_placement.h> 8 + 9 + #include "ttm_mock_manager.h" 10 + 11 + static inline struct ttm_mock_manager * 12 + to_mock_mgr(struct ttm_resource_manager *man) 13 + { 14 + return container_of(man, struct ttm_mock_manager, man); 15 + } 16 + 17 + static inline struct ttm_mock_resource * 18 + to_mock_mgr_resource(struct ttm_resource *res) 19 + { 20 + return container_of(res, struct ttm_mock_resource, base); 21 + } 22 + 23 + static int ttm_mock_manager_alloc(struct ttm_resource_manager *man, 24 + struct ttm_buffer_object *bo, 25 + const struct ttm_place *place, 26 + struct ttm_resource **res) 27 + { 28 + struct ttm_mock_manager *manager = to_mock_mgr(man); 29 + struct ttm_mock_resource *mock_res; 30 + struct drm_buddy *mm = &manager->mm; 31 + u64 lpfn, fpfn, alloc_size; 32 + int err; 33 + 34 + mock_res = kzalloc(sizeof(*mock_res), GFP_KERNEL); 35 + 36 + if (!mock_res) 37 + return -ENOMEM; 38 + 39 + fpfn = 0; 40 + lpfn = man->size; 41 + 42 + ttm_resource_init(bo, place, &mock_res->base); 43 + INIT_LIST_HEAD(&mock_res->blocks); 44 + 45 + if (place->flags & TTM_PL_FLAG_TOPDOWN) 46 + mock_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION; 47 + 48 + if (place->flags & TTM_PL_FLAG_CONTIGUOUS) 49 + mock_res->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION; 50 + 51 + alloc_size = (uint64_t)mock_res->base.size; 52 + mutex_lock(&manager->lock); 53 + err = drm_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size, 54 + manager->default_page_size, 55 + &mock_res->blocks, 56 + mock_res->flags); 57 + 58 + if (err) 59 + goto error_free_blocks; 60 + mutex_unlock(&manager->lock); 61 + 62 + *res = &mock_res->base; 63 + return 0; 64 + 65 + error_free_blocks: 66 + drm_buddy_free_list(mm, &mock_res->blocks, 0); 67 + ttm_resource_fini(man, &mock_res->base); 68 + mutex_unlock(&manager->lock); 69 + 70 + return err; 71 + } 72 + 73 + static void ttm_mock_manager_free(struct ttm_resource_manager *man, 74 + struct ttm_resource *res) 75 + { 76 + struct ttm_mock_manager *manager = to_mock_mgr(man); 77 + struct ttm_mock_resource *mock_res = to_mock_mgr_resource(res); 78 + struct drm_buddy *mm = &manager->mm; 79 + 80 + mutex_lock(&manager->lock); 81 + drm_buddy_free_list(mm, &mock_res->blocks, 0); 82 + mutex_unlock(&manager->lock); 83 + 84 + ttm_resource_fini(man, res); 85 + kfree(mock_res); 86 + } 87 + 88 + static const struct ttm_resource_manager_func ttm_mock_manager_funcs = { 89 + .alloc = ttm_mock_manager_alloc, 90 + .free = ttm_mock_manager_free, 91 + }; 92 + 93 + int ttm_mock_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size) 94 + { 95 + struct ttm_mock_manager *manager; 96 + struct ttm_resource_manager *base; 97 + int err; 98 + 99 + manager = kzalloc(sizeof(*manager), GFP_KERNEL); 100 + if (!manager) 101 + return -ENOMEM; 102 + 103 + mutex_init(&manager->lock); 104 + 105 + err = drm_buddy_init(&manager->mm, size, PAGE_SIZE); 106 + 107 + if (err) { 108 + kfree(manager); 109 + return err; 110 + } 111 + 112 + manager->default_page_size = PAGE_SIZE; 113 + base = &manager->man; 114 + base->func = &ttm_mock_manager_funcs; 115 + base->use_tt = true; 116 + 117 + ttm_resource_manager_init(base, bdev, size); 118 + ttm_set_driver_manager(bdev, mem_type, base); 119 + ttm_resource_manager_set_used(base, true); 120 + 121 + return 0; 122 + } 123 + EXPORT_SYMBOL_GPL(ttm_mock_manager_init); 124 + 125 + void ttm_mock_manager_fini(struct ttm_device *bdev, u32 mem_type) 126 + { 127 + struct ttm_resource_manager *man; 128 + struct ttm_mock_manager *mock_man; 129 + int err; 130 + 131 + man = ttm_manager_type(bdev, mem_type); 132 + mock_man = to_mock_mgr(man); 133 + 134 + err = ttm_resource_manager_evict_all(bdev, man); 135 + if (err) 136 + return; 137 + 138 + ttm_resource_manager_set_used(man, false); 139 + 140 + mutex_lock(&mock_man->lock); 141 + drm_buddy_fini(&mock_man->mm); 142 + mutex_unlock(&mock_man->lock); 143 + 144 + ttm_set_driver_manager(bdev, mem_type, NULL); 145 + } 146 + EXPORT_SYMBOL_GPL(ttm_mock_manager_fini); 147 + 148 + static int ttm_bad_manager_alloc(struct ttm_resource_manager *man, 149 + struct ttm_buffer_object *bo, 150 + const struct ttm_place *place, 151 + struct ttm_resource **res) 152 + { 153 + return -ENOSPC; 154 + } 155 + 156 + static int ttm_busy_manager_alloc(struct ttm_resource_manager *man, 157 + struct ttm_buffer_object *bo, 158 + const struct ttm_place *place, 159 + struct ttm_resource **res) 160 + { 161 + return -EBUSY; 162 + } 163 + 164 + static void ttm_bad_manager_free(struct ttm_resource_manager *man, 165 + struct ttm_resource *res) 166 + { 167 + } 168 + 169 + static bool ttm_bad_manager_compatible(struct ttm_resource_manager *man, 170 + struct ttm_resource *res, 171 + const struct ttm_place *place, 172 + size_t size) 173 + { 174 + return true; 175 + } 176 + 177 + static const struct ttm_resource_manager_func ttm_bad_manager_funcs = { 178 + .alloc = ttm_bad_manager_alloc, 179 + .free = ttm_bad_manager_free, 180 + .compatible = ttm_bad_manager_compatible 181 + }; 182 + 183 + static const struct ttm_resource_manager_func ttm_bad_busy_manager_funcs = { 184 + .alloc = ttm_busy_manager_alloc, 185 + .free = ttm_bad_manager_free, 186 + .compatible = ttm_bad_manager_compatible 187 + }; 188 + 189 + int ttm_bad_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size) 190 + { 191 + struct ttm_resource_manager *man; 192 + 193 + man = kzalloc(sizeof(*man), GFP_KERNEL); 194 + if (!man) 195 + return -ENOMEM; 196 + 197 + man->func = &ttm_bad_manager_funcs; 198 + 199 + ttm_resource_manager_init(man, bdev, size); 200 + ttm_set_driver_manager(bdev, mem_type, man); 201 + ttm_resource_manager_set_used(man, true); 202 + 203 + return 0; 204 + } 205 + EXPORT_SYMBOL_GPL(ttm_bad_manager_init); 206 + 207 + int ttm_busy_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size) 208 + { 209 + struct ttm_resource_manager *man; 210 + 211 + ttm_bad_manager_init(bdev, mem_type, size); 212 + man = ttm_manager_type(bdev, mem_type); 213 + 214 + man->func = &ttm_bad_busy_manager_funcs; 215 + 216 + return 0; 217 + } 218 + EXPORT_SYMBOL_GPL(ttm_busy_manager_init); 219 + 220 + void ttm_bad_manager_fini(struct ttm_device *bdev, uint32_t mem_type) 221 + { 222 + struct ttm_resource_manager *man; 223 + 224 + man = ttm_manager_type(bdev, mem_type); 225 + 226 + ttm_resource_manager_set_used(man, false); 227 + ttm_set_driver_manager(bdev, mem_type, NULL); 228 + 229 + kfree(man); 230 + } 231 + EXPORT_SYMBOL_GPL(ttm_bad_manager_fini); 232 + 233 + MODULE_DESCRIPTION("KUnit tests for ttm with mock resource managers"); 234 + MODULE_LICENSE("GPL and additional rights");
+30
drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 AND MIT */ 2 + /* 3 + * Copyright © 2023 Intel Corporation 4 + */ 5 + #ifndef TTM_MOCK_MANAGER_H 6 + #define TTM_MOCK_MANAGER_H 7 + 8 + #include <drm/drm_buddy.h> 9 + 10 + struct ttm_mock_manager { 11 + struct ttm_resource_manager man; 12 + struct drm_buddy mm; 13 + u64 default_page_size; 14 + /* protects allocations of mock buffer objects */ 15 + struct mutex lock; 16 + }; 17 + 18 + struct ttm_mock_resource { 19 + struct ttm_resource base; 20 + struct list_head blocks; 21 + unsigned long flags; 22 + }; 23 + 24 + int ttm_mock_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size); 25 + int ttm_bad_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size); 26 + int ttm_busy_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size); 27 + void ttm_mock_manager_fini(struct ttm_device *bdev, u32 mem_type); 28 + void ttm_bad_manager_fini(struct ttm_device *bdev, u32 mem_type); 29 + 30 + #endif // TTM_MOCK_MANAGER_H
+5 -4
drivers/gpu/drm/ttm/tests/ttm_pool_test.c
··· 48 48 } 49 49 50 50 static struct ttm_tt *ttm_tt_kunit_init(struct kunit *test, 51 - uint32_t page_flags, 51 + u32 page_flags, 52 52 enum ttm_caching caching, 53 53 size_t size) 54 54 { ··· 57 57 struct ttm_tt *tt; 58 58 int err; 59 59 60 - bo = ttm_bo_kunit_init(test, priv->devs, size); 60 + bo = ttm_bo_kunit_init(test, priv->devs, size, NULL); 61 61 KUNIT_ASSERT_NOT_NULL(test, bo); 62 62 priv->mock_bo = bo; 63 63 ··· 209 209 tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL); 210 210 KUNIT_ASSERT_NOT_NULL(test, tt); 211 211 212 - bo = ttm_bo_kunit_init(test, devs, size); 212 + bo = ttm_bo_kunit_init(test, devs, size, NULL); 213 213 KUNIT_ASSERT_NOT_NULL(test, bo); 214 214 215 215 err = ttm_sg_tt_init(tt, bo, 0, caching); ··· 433 433 434 434 kunit_test_suites(&ttm_pool_test_suite); 435 435 436 - MODULE_LICENSE("GPL"); 436 + MODULE_DESCRIPTION("KUnit tests for ttm_pool APIs"); 437 + MODULE_LICENSE("GPL and additional rights");
+11 -10
drivers/gpu/drm/ttm/tests/ttm_resource_test.c
··· 11 11 12 12 struct ttm_resource_test_case { 13 13 const char *description; 14 - uint32_t mem_type; 15 - uint32_t flags; 14 + u32 mem_type; 15 + u32 flags; 16 16 }; 17 17 18 18 struct ttm_resource_test_priv { ··· 47 47 48 48 static void ttm_init_test_mocks(struct kunit *test, 49 49 struct ttm_resource_test_priv *priv, 50 - uint32_t mem_type, uint32_t flags) 50 + u32 mem_type, u32 flags) 51 51 { 52 52 size_t size = RES_SIZE; 53 53 54 54 /* Make sure we have what we need for a good BO mock */ 55 55 KUNIT_ASSERT_NOT_NULL(test, priv->devs->ttm_dev); 56 56 57 - priv->bo = ttm_bo_kunit_init(test, priv->devs, size); 57 + priv->bo = ttm_bo_kunit_init(test, priv->devs, size, NULL); 58 58 priv->place = ttm_place_kunit_init(test, mem_type, flags); 59 59 } 60 60 61 61 static void ttm_init_test_manager(struct kunit *test, 62 62 struct ttm_resource_test_priv *priv, 63 - uint32_t mem_type) 63 + u32 mem_type) 64 64 { 65 65 struct ttm_device *ttm_dev = priv->devs->ttm_dev; 66 66 struct ttm_resource_manager *man; ··· 112 112 struct ttm_buffer_object *bo; 113 113 struct ttm_place *place; 114 114 struct ttm_resource_manager *man; 115 - uint64_t expected_usage; 115 + u64 expected_usage; 116 116 117 117 ttm_init_test_mocks(test, priv, params->mem_type, params->flags); 118 118 bo = priv->bo; ··· 230 230 struct ttm_buffer_object *bo; 231 231 struct ttm_place *place; 232 232 struct ttm_resource_manager *man; 233 - uint64_t actual_usage; 233 + u64 actual_usage; 234 234 235 235 ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, TTM_PL_FLAG_TOPDOWN); 236 236 bo = priv->bo; ··· 268 268 struct ttm_buffer_object *bo; 269 269 struct ttm_place *place; 270 270 struct ttm_resource *res; 271 - uint32_t mem_type = TTM_PL_SYSTEM; 271 + u32 mem_type = TTM_PL_SYSTEM; 272 272 int ret; 273 273 274 274 ttm_init_test_mocks(test, priv, mem_type, 0); ··· 293 293 struct ttm_buffer_object *bo; 294 294 struct ttm_place *place; 295 295 struct ttm_resource *res; 296 - uint32_t mem_type = TTM_PL_SYSTEM; 296 + u32 mem_type = TTM_PL_SYSTEM; 297 297 298 298 ttm_init_test_mocks(test, priv, mem_type, 0); 299 299 bo = priv->bo; ··· 332 332 333 333 kunit_test_suites(&ttm_resource_test_suite); 334 334 335 - MODULE_LICENSE("GPL"); 335 + MODULE_DESCRIPTION("KUnit tests for ttm_resource and ttm_sys_man APIs"); 336 + MODULE_LICENSE("GPL and additional rights");
+138 -31
drivers/gpu/drm/ttm/tests/ttm_tt_test.c
··· 11 11 12 12 struct ttm_tt_test_case { 13 13 const char *description; 14 - uint32_t size; 15 - uint32_t extra_pages_num; 14 + u32 size; 15 + u32 extra_pages_num; 16 16 }; 17 - 18 - static int ttm_tt_test_init(struct kunit *test) 19 - { 20 - struct ttm_test_devices *priv; 21 - 22 - priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); 23 - KUNIT_ASSERT_NOT_NULL(test, priv); 24 - 25 - priv = ttm_test_devices_all(test); 26 - test->priv = priv; 27 - 28 - return 0; 29 - } 30 17 31 18 static const struct ttm_tt_test_case ttm_tt_init_basic_cases[] = { 32 19 { ··· 41 54 const struct ttm_tt_test_case *params = test->param_value; 42 55 struct ttm_buffer_object *bo; 43 56 struct ttm_tt *tt; 44 - uint32_t page_flags = TTM_TT_FLAG_ZERO_ALLOC; 57 + u32 page_flags = TTM_TT_FLAG_ZERO_ALLOC; 45 58 enum ttm_caching caching = ttm_cached; 46 - uint32_t extra_pages = params->extra_pages_num; 59 + u32 extra_pages = params->extra_pages_num; 47 60 int num_pages = params->size >> PAGE_SHIFT; 48 61 int err; 49 62 50 63 tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL); 51 64 KUNIT_ASSERT_NOT_NULL(test, tt); 52 65 53 - bo = ttm_bo_kunit_init(test, test->priv, params->size); 66 + bo = ttm_bo_kunit_init(test, test->priv, params->size, NULL); 54 67 55 68 err = ttm_tt_init(tt, bo, page_flags, caching, extra_pages); 56 69 KUNIT_ASSERT_EQ(test, err, 0); ··· 69 82 struct ttm_buffer_object *bo; 70 83 struct ttm_tt *tt; 71 84 enum ttm_caching caching = ttm_cached; 72 - uint32_t size = SZ_8K; 85 + u32 size = SZ_8K; 73 86 int num_pages = (size + SZ_4K) >> PAGE_SHIFT; 74 87 int err; 75 88 76 89 tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL); 77 90 KUNIT_ASSERT_NOT_NULL(test, tt); 78 91 79 - bo = ttm_bo_kunit_init(test, test->priv, size); 92 + bo = ttm_bo_kunit_init(test, test->priv, size, NULL); 80 93 81 94 /* Make the object size misaligned */ 82 95 bo->base.size += 1; ··· 97 110 tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL); 98 111 KUNIT_ASSERT_NOT_NULL(test, tt); 99 112 100 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 113 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 101 114 102 115 err = ttm_tt_init(tt, bo, 0, caching, 0); 103 116 KUNIT_ASSERT_EQ(test, err, 0); ··· 117 130 tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL); 118 131 KUNIT_ASSERT_NOT_NULL(test, tt); 119 132 120 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 133 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 121 134 122 135 err = ttm_sg_tt_init(tt, bo, 0, caching); 123 136 KUNIT_ASSERT_EQ(test, err, 0); ··· 138 151 tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL); 139 152 KUNIT_ASSERT_NOT_NULL(test, tt); 140 153 141 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 154 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 142 155 143 156 err = ttm_tt_init(tt, bo, 0, caching, 0); 144 157 KUNIT_ASSERT_EQ(test, err, 0); ··· 155 168 struct ttm_buffer_object *bo; 156 169 int err; 157 170 158 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 171 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 159 172 bo->type = ttm_bo_type_device; 160 173 161 174 dma_resv_lock(bo->base.resv, NULL); ··· 174 187 struct ttm_buffer_object *bo; 175 188 int err; 176 189 177 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 190 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 178 191 bo->type = ttm_bo_type_sg + 1; 179 192 180 193 dma_resv_lock(bo->base.resv, NULL); ··· 195 208 tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL); 196 209 KUNIT_ASSERT_NOT_NULL(test, tt); 197 210 198 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 211 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 199 212 200 213 err = ttm_tt_init(tt, bo, 0, caching, 0); 201 214 KUNIT_ASSERT_EQ(test, err, 0); ··· 211 224 } 212 225 213 226 static struct ttm_tt *ttm_tt_null_create(struct ttm_buffer_object *bo, 214 - uint32_t page_flags) 227 + u32 page_flags) 215 228 { 216 229 return NULL; 217 230 } ··· 226 239 struct ttm_buffer_object *bo; 227 240 int err; 228 241 229 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 242 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 230 243 231 244 /* Update ttm_device_funcs so we don't alloc ttm_tt */ 232 245 devs->ttm_dev->funcs = &ttm_dev_empty_funcs; ··· 244 257 struct ttm_buffer_object *bo; 245 258 int err; 246 259 247 - bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE); 260 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 248 261 249 262 dma_resv_lock(bo->base.resv, NULL); 250 263 err = ttm_tt_create(bo, false); ··· 254 267 KUNIT_ASSERT_NOT_NULL(test, bo->ttm); 255 268 256 269 ttm_tt_destroy(devs->ttm_dev, bo->ttm); 270 + } 271 + 272 + static void ttm_tt_populate_null_ttm(struct kunit *test) 273 + { 274 + const struct ttm_test_devices *devs = test->priv; 275 + struct ttm_operation_ctx ctx = { }; 276 + int err; 277 + 278 + err = ttm_tt_populate(devs->ttm_dev, NULL, &ctx); 279 + KUNIT_ASSERT_EQ(test, err, -EINVAL); 280 + } 281 + 282 + static void ttm_tt_populate_populated_ttm(struct kunit *test) 283 + { 284 + const struct ttm_test_devices *devs = test->priv; 285 + struct ttm_operation_ctx ctx = { }; 286 + struct ttm_buffer_object *bo; 287 + struct ttm_tt *tt; 288 + struct page *populated_page; 289 + int err; 290 + 291 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 292 + 293 + tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL); 294 + KUNIT_ASSERT_NOT_NULL(test, tt); 295 + 296 + err = ttm_tt_init(tt, bo, 0, ttm_cached, 0); 297 + KUNIT_ASSERT_EQ(test, err, 0); 298 + 299 + err = ttm_tt_populate(devs->ttm_dev, tt, &ctx); 300 + KUNIT_ASSERT_EQ(test, err, 0); 301 + populated_page = *tt->pages; 302 + 303 + err = ttm_tt_populate(devs->ttm_dev, tt, &ctx); 304 + KUNIT_ASSERT_PTR_EQ(test, populated_page, *tt->pages); 305 + } 306 + 307 + static void ttm_tt_unpopulate_basic(struct kunit *test) 308 + { 309 + const struct ttm_test_devices *devs = test->priv; 310 + struct ttm_operation_ctx ctx = { }; 311 + struct ttm_buffer_object *bo; 312 + struct ttm_tt *tt; 313 + int err; 314 + 315 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 316 + 317 + tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL); 318 + KUNIT_ASSERT_NOT_NULL(test, tt); 319 + 320 + err = ttm_tt_init(tt, bo, 0, ttm_cached, 0); 321 + KUNIT_ASSERT_EQ(test, err, 0); 322 + 323 + err = ttm_tt_populate(devs->ttm_dev, tt, &ctx); 324 + KUNIT_ASSERT_EQ(test, err, 0); 325 + KUNIT_ASSERT_TRUE(test, ttm_tt_is_populated(tt)); 326 + 327 + ttm_tt_unpopulate(devs->ttm_dev, tt); 328 + KUNIT_ASSERT_FALSE(test, ttm_tt_is_populated(tt)); 329 + } 330 + 331 + static void ttm_tt_unpopulate_empty_ttm(struct kunit *test) 332 + { 333 + const struct ttm_test_devices *devs = test->priv; 334 + struct ttm_buffer_object *bo; 335 + struct ttm_tt *tt; 336 + int err; 337 + 338 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 339 + 340 + tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL); 341 + KUNIT_ASSERT_NOT_NULL(test, tt); 342 + 343 + err = ttm_tt_init(tt, bo, 0, ttm_cached, 0); 344 + KUNIT_ASSERT_EQ(test, err, 0); 345 + 346 + ttm_tt_unpopulate(devs->ttm_dev, tt); 347 + /* Expect graceful handling of unpopulated TTs */ 348 + } 349 + 350 + static void ttm_tt_swapin_basic(struct kunit *test) 351 + { 352 + const struct ttm_test_devices *devs = test->priv; 353 + int expected_num_pages = BO_SIZE >> PAGE_SHIFT; 354 + struct ttm_operation_ctx ctx = { }; 355 + struct ttm_buffer_object *bo; 356 + struct ttm_tt *tt; 357 + int err, num_pages; 358 + 359 + bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL); 360 + 361 + tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL); 362 + KUNIT_ASSERT_NOT_NULL(test, tt); 363 + 364 + err = ttm_tt_init(tt, bo, 0, ttm_cached, 0); 365 + KUNIT_ASSERT_EQ(test, err, 0); 366 + 367 + err = ttm_tt_populate(devs->ttm_dev, tt, &ctx); 368 + KUNIT_ASSERT_EQ(test, err, 0); 369 + KUNIT_ASSERT_TRUE(test, ttm_tt_is_populated(tt)); 370 + 371 + num_pages = ttm_tt_swapout(devs->ttm_dev, tt, GFP_KERNEL); 372 + KUNIT_ASSERT_EQ(test, num_pages, expected_num_pages); 373 + KUNIT_ASSERT_NOT_NULL(test, tt->swap_storage); 374 + KUNIT_ASSERT_TRUE(test, tt->page_flags & TTM_TT_FLAG_SWAPPED); 375 + 376 + /* Swapout depopulates TT, allocate pages and then swap them in */ 377 + err = ttm_pool_alloc(&devs->ttm_dev->pool, tt, &ctx); 378 + KUNIT_ASSERT_EQ(test, err, 0); 379 + 380 + err = ttm_tt_swapin(tt); 381 + KUNIT_ASSERT_EQ(test, err, 0); 382 + KUNIT_ASSERT_NULL(test, tt->swap_storage); 383 + KUNIT_ASSERT_FALSE(test, tt->page_flags & TTM_TT_FLAG_SWAPPED); 257 384 } 258 385 259 386 static struct kunit_case ttm_tt_test_cases[] = { ··· 381 280 KUNIT_CASE(ttm_tt_create_ttm_exists), 382 281 KUNIT_CASE(ttm_tt_create_failed), 383 282 KUNIT_CASE(ttm_tt_destroy_basic), 283 + KUNIT_CASE(ttm_tt_populate_null_ttm), 284 + KUNIT_CASE(ttm_tt_populate_populated_ttm), 285 + KUNIT_CASE(ttm_tt_unpopulate_basic), 286 + KUNIT_CASE(ttm_tt_unpopulate_empty_ttm), 287 + KUNIT_CASE(ttm_tt_swapin_basic), 384 288 {} 385 289 }; 386 290 387 291 static struct kunit_suite ttm_tt_test_suite = { 388 292 .name = "ttm_tt", 389 - .init = ttm_tt_test_init, 293 + .init = ttm_test_devices_all_init, 390 294 .exit = ttm_test_devices_fini, 391 295 .test_cases = ttm_tt_test_cases, 392 296 }; 393 297 394 298 kunit_test_suites(&ttm_tt_test_suite); 395 299 396 - MODULE_LICENSE("GPL"); 300 + MODULE_DESCRIPTION("KUnit tests for ttm_tt APIs"); 301 + MODULE_LICENSE("GPL and additional rights");
+3
drivers/gpu/drm/ttm/ttm_tt.c
··· 251 251 out_err: 252 252 return ret; 253 253 } 254 + EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_swapin); 254 255 255 256 /** 256 257 * ttm_tt_swapout - swap out tt object ··· 309 308 310 309 return ret; 311 310 } 311 + EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_swapout); 312 312 313 313 int ttm_tt_populate(struct ttm_device *bdev, 314 314 struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) ··· 388 386 389 387 ttm->page_flags &= ~TTM_TT_FLAG_PRIV_POPULATED; 390 388 } 389 + EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_unpopulate); 391 390 392 391 #ifdef CONFIG_DEBUG_FS 393 392
+30 -1
drivers/gpu/drm/vc4/vc4_vec.c
··· 234 234 VC4_VEC_TV_MODE_PAL_60, 235 235 VC4_VEC_TV_MODE_PAL_N, 236 236 VC4_VEC_TV_MODE_SECAM, 237 + VC4_VEC_TV_MODE_MONOCHROME, 237 238 }; 238 239 239 240 struct vc4_vec_tv_mode { ··· 325 324 .config1 = VEC_CONFIG1_C_CVBS_CVBS, 326 325 .custom_freq = 0x29c71c72, 327 326 }, 327 + { 328 + /* 50Hz mono */ 329 + .mode = DRM_MODE_TV_MODE_MONOCHROME, 330 + .expected_htotal = 864, 331 + .config0 = VEC_CONFIG0_PAL_BDGHI_STD | VEC_CONFIG0_BURDIS | 332 + VEC_CONFIG0_CHRDIS, 333 + .config1 = VEC_CONFIG1_C_CVBS_CVBS, 334 + }, 335 + { 336 + /* 60Hz mono */ 337 + .mode = DRM_MODE_TV_MODE_MONOCHROME, 338 + .expected_htotal = 858, 339 + .config0 = VEC_CONFIG0_PAL_M_STD | VEC_CONFIG0_BURDIS | 340 + VEC_CONFIG0_CHRDIS, 341 + .config1 = VEC_CONFIG1_C_CVBS_CVBS, 342 + }, 328 343 }; 329 344 330 345 static inline const struct vc4_vec_tv_mode * ··· 368 351 { VC4_VEC_TV_MODE_PAL_M, "PAL-M", }, 369 352 { VC4_VEC_TV_MODE_PAL_N, "PAL-N", }, 370 353 { VC4_VEC_TV_MODE_SECAM, "SECAM", }, 354 + { VC4_VEC_TV_MODE_MONOCHROME, "Mono", }, 371 355 }; 372 356 373 357 static enum drm_connector_status ··· 424 406 state->tv.mode = DRM_MODE_TV_MODE_SECAM; 425 407 break; 426 408 409 + case VC4_VEC_TV_MODE_MONOCHROME: 410 + state->tv.mode = DRM_MODE_TV_MODE_MONOCHROME; 411 + break; 412 + 427 413 default: 428 414 return -EINVAL; 429 415 } ··· 473 451 474 452 case DRM_MODE_TV_MODE_SECAM: 475 453 *val = VC4_VEC_TV_MODE_SECAM; 454 + break; 455 + 456 + case DRM_MODE_TV_MODE_MONOCHROME: 457 + *val = VC4_VEC_TV_MODE_MONOCHROME; 476 458 break; 477 459 478 460 default: ··· 528 502 vec->legacy_tv_mode_property = prop; 529 503 530 504 drm_object_attach_property(&connector->base, prop, VC4_VEC_TV_MODE_NTSC); 505 + 506 + drm_connector_attach_tv_margin_properties(connector); 531 507 532 508 drm_connector_attach_encoder(connector, &vec->encoder.base); 533 509 ··· 782 754 BIT(DRM_MODE_TV_MODE_PAL) | 783 755 BIT(DRM_MODE_TV_MODE_PAL_M) | 784 756 BIT(DRM_MODE_TV_MODE_PAL_N) | 785 - BIT(DRM_MODE_TV_MODE_SECAM)); 757 + BIT(DRM_MODE_TV_MODE_SECAM) | 758 + BIT(DRM_MODE_TV_MODE_MONOCHROME)); 786 759 if (ret) 787 760 return ret; 788 761
+85 -46
drivers/gpu/ipu-v3/ipu-pre.c
··· 5 5 6 6 #include <drm/drm_fourcc.h> 7 7 #include <linux/clk.h> 8 + #include <linux/delay.h> 8 9 #include <linux/err.h> 9 10 #include <linux/genalloc.h> 10 11 #include <linux/module.h> ··· 97 96 98 97 dma_addr_t buffer_paddr; 99 98 void *buffer_virt; 100 - bool in_use; 101 - unsigned int safe_window_end; 102 - unsigned int last_bufaddr; 99 + 100 + struct { 101 + bool in_use; 102 + uint64_t modifier; 103 + unsigned int height; 104 + unsigned int safe_window_end; 105 + unsigned int bufaddr; 106 + u32 ctrl; 107 + u8 cpp; 108 + } cur; 103 109 }; 104 110 105 111 static DEFINE_MUTEX(ipu_pre_list_mutex); ··· 121 113 struct ipu_pre * 122 114 ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index) 123 115 { 124 - struct device_node *pre_node = of_parse_phandle(dev->of_node, 125 - name, index); 116 + struct device_node *pre_node __free(device_node) = 117 + of_parse_phandle(dev->of_node, name, index); 126 118 struct ipu_pre *pre; 127 119 128 120 mutex_lock(&ipu_pre_list_mutex); ··· 131 123 mutex_unlock(&ipu_pre_list_mutex); 132 124 device_link_add(dev, pre->dev, 133 125 DL_FLAG_AUTOREMOVE_CONSUMER); 134 - of_node_put(pre_node); 135 126 return pre; 136 127 } 137 128 } 138 129 mutex_unlock(&ipu_pre_list_mutex); 139 - 140 - of_node_put(pre_node); 141 130 142 131 return NULL; 143 132 } ··· 143 138 { 144 139 u32 val; 145 140 146 - if (pre->in_use) 141 + if (pre->cur.in_use) 147 142 return -EBUSY; 148 143 149 144 /* first get the engine out of reset and remove clock gating */ ··· 156 151 IPU_PRE_CTRL_SDW_UPDATE; 157 152 writel(val, pre->regs + IPU_PRE_CTRL); 158 153 159 - pre->in_use = true; 154 + pre->cur.in_use = true; 160 155 return 0; 161 156 } 162 157 ··· 164 159 { 165 160 writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL); 166 161 167 - pre->in_use = false; 162 + pre->cur.in_use = false; 163 + } 164 + 165 + static inline void 166 + ipu_pre_update_safe_window(struct ipu_pre *pre) 167 + { 168 + if (pre->cur.modifier == DRM_FORMAT_MOD_LINEAR) 169 + pre->cur.safe_window_end = pre->cur.height - 2; 170 + else 171 + pre->cur.safe_window_end = DIV_ROUND_UP(pre->cur.height, 4) - 1; 172 + } 173 + 174 + static void 175 + ipu_pre_configure_modifier(struct ipu_pre *pre, uint64_t modifier) 176 + { 177 + u32 val; 178 + 179 + val = readl(pre->regs + IPU_PRE_TPR_CTRL); 180 + val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK; 181 + if (modifier != DRM_FORMAT_MOD_LINEAR) { 182 + /* only support single buffer formats for now */ 183 + val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF; 184 + if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED) 185 + val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED; 186 + if (pre->cur.cpp == 2) 187 + val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT; 188 + } 189 + writel(val, pre->regs + IPU_PRE_TPR_CTRL); 190 + 191 + if (modifier == DRM_FORMAT_MOD_LINEAR) 192 + pre->cur.ctrl &= ~IPU_PRE_CTRL_BLOCK_EN; 193 + else 194 + pre->cur.ctrl |= IPU_PRE_CTRL_BLOCK_EN; 195 + 196 + pre->cur.modifier = modifier; 168 197 } 169 198 170 199 void ipu_pre_configure(struct ipu_pre *pre, unsigned int width, ··· 209 170 u32 active_bpp = info->cpp[0] >> 1; 210 171 u32 val; 211 172 173 + pre->cur.bufaddr = bufaddr; 174 + pre->cur.height = height; 175 + pre->cur.cpp = info->cpp[0]; 176 + pre->cur.ctrl = readl(pre->regs + IPU_PRE_CTRL); 177 + 212 178 /* calculate safe window for ctrl register updates */ 213 - if (modifier == DRM_FORMAT_MOD_LINEAR) 214 - pre->safe_window_end = height - 2; 215 - else 216 - pre->safe_window_end = DIV_ROUND_UP(height, 4) - 1; 179 + ipu_pre_update_safe_window(pre); 217 180 218 181 writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF); 219 182 writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF); 220 - pre->last_bufaddr = bufaddr; 221 183 222 184 val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) | 223 185 IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) | ··· 248 208 249 209 writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR); 250 210 251 - val = readl(pre->regs + IPU_PRE_TPR_CTRL); 252 - val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK; 253 - if (modifier != DRM_FORMAT_MOD_LINEAR) { 254 - /* only support single buffer formats for now */ 255 - val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF; 256 - if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED) 257 - val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED; 258 - if (info->cpp[0] == 2) 259 - val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT; 260 - } 261 - writel(val, pre->regs + IPU_PRE_TPR_CTRL); 211 + ipu_pre_configure_modifier(pre, modifier); 262 212 263 - val = readl(pre->regs + IPU_PRE_CTRL); 264 - val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE | 265 - IPU_PRE_CTRL_SDW_UPDATE; 266 - if (modifier == DRM_FORMAT_MOD_LINEAR) 267 - val &= ~IPU_PRE_CTRL_BLOCK_EN; 268 - else 269 - val |= IPU_PRE_CTRL_BLOCK_EN; 270 - writel(val, pre->regs + IPU_PRE_CTRL); 213 + pre->cur.ctrl |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE; 214 + writel(pre->cur.ctrl | IPU_PRE_CTRL_SDW_UPDATE, 215 + pre->regs + IPU_PRE_CTRL); 271 216 } 272 217 273 - void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr) 218 + void ipu_pre_update(struct ipu_pre *pre, uint64_t modifier, unsigned int bufaddr) 274 219 { 275 - unsigned long timeout = jiffies + msecs_to_jiffies(5); 276 - unsigned short current_yblock; 277 - u32 val; 278 - 279 - if (bufaddr == pre->last_bufaddr) 220 + if (bufaddr == pre->cur.bufaddr && 221 + modifier == pre->cur.modifier) 280 222 return; 281 223 282 224 writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF); 283 - pre->last_bufaddr = bufaddr; 225 + pre->cur.bufaddr = bufaddr; 284 226 285 - do { 286 - if (time_after(jiffies, timeout)) { 227 + if (modifier != pre->cur.modifier) 228 + ipu_pre_configure_modifier(pre, modifier); 229 + 230 + for (int i = 0;; i++) { 231 + unsigned short current_yblock; 232 + u32 val; 233 + 234 + if (i > 500) { 287 235 dev_warn(pre->dev, "timeout waiting for PRE safe window\n"); 288 236 return; 289 237 } ··· 280 252 current_yblock = 281 253 (val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) & 282 254 IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK; 283 - } while (current_yblock == 0 || current_yblock >= pre->safe_window_end); 284 255 285 - writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET); 256 + if (current_yblock != 0 && 257 + current_yblock < pre->cur.safe_window_end) 258 + break; 259 + 260 + udelay(10); 261 + cpu_relax(); 262 + } 263 + 264 + writel(pre->cur.ctrl | IPU_PRE_CTRL_SDW_UPDATE, 265 + pre->regs + IPU_PRE_CTRL); 266 + 267 + /* calculate safe window for the next update with the new modifier */ 268 + ipu_pre_update_safe_window(pre); 286 269 } 287 270 288 271 bool ipu_pre_update_pending(struct ipu_pre *pre)
+1 -1
drivers/gpu/ipu-v3/ipu-prg.c
··· 287 287 chan = &prg->chan[prg_chan]; 288 288 289 289 if (chan->enabled) { 290 - ipu_pre_update(prg->pres[chan->used_pre], *eba); 290 + ipu_pre_update(prg->pres[chan->used_pre], modifier, *eba); 291 291 return 0; 292 292 } 293 293
+1 -1
drivers/gpu/ipu-v3/ipu-prv.h
··· 263 263 void ipu_pre_configure(struct ipu_pre *pre, unsigned int width, 264 264 unsigned int height, unsigned int stride, u32 format, 265 265 uint64_t modifier, unsigned int bufaddr); 266 - void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr); 266 + void ipu_pre_update(struct ipu_pre *pre, uint64_t modifier, unsigned int bufaddr); 267 267 bool ipu_pre_update_pending(struct ipu_pre *pre); 268 268 269 269 struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
+2
drivers/video/logo/Kconfig
··· 8 8 depends on FB_CORE || SGI_NEWPORT_CONSOLE 9 9 help 10 10 Enable and select frame buffer bootup logos. 11 + Monochrome logos will also be used by the DRM panic handler, if 12 + enabled. 11 13 12 14 if LOGO 13 15
+1 -3
include/drm/bridge/analogix_dp.h
··· 29 29 struct drm_connector *connector; 30 30 bool skip_connector; 31 31 32 - int (*power_on_start)(struct analogix_dp_plat_data *); 33 - int (*power_on_end)(struct analogix_dp_plat_data *); 32 + int (*power_on)(struct analogix_dp_plat_data *); 34 33 int (*power_off)(struct analogix_dp_plat_data *); 35 34 int (*attach)(struct analogix_dp_plat_data *, struct drm_bridge *, 36 35 struct drm_connector *); ··· 44 45 analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data); 45 46 int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev); 46 47 void analogix_dp_unbind(struct analogix_dp_device *dp); 47 - void analogix_dp_remove(struct analogix_dp_device *dp); 48 48 49 49 int analogix_dp_start_crc(struct drm_connector *connector); 50 50 int analogix_dp_stop_crc(struct drm_connector *connector);
+1 -1
include/drm/display/drm_hdmi_state_helper.h
··· 16 16 17 17 int drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *connector, 18 18 struct hdmi_audio_infoframe *frame); 19 - int drm_atomic_helper_connector_hdmi_disable_audio_infoframe(struct drm_connector *connector); 19 + int drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *connector); 20 20 int drm_atomic_helper_connector_hdmi_update_infoframes(struct drm_connector *connector, 21 21 struct drm_atomic_state *state); 22 22
+7
include/drm/drm_mipi_dsi.h
··· 10 10 #define __DRM_MIPI_DSI_H__ 11 11 12 12 #include <linux/device.h> 13 + #include <linux/delay.h> 13 14 14 15 struct mipi_dsi_host; 15 16 struct mipi_dsi_device; ··· 296 295 do { \ 297 296 if (!(ctx)->accum_err) \ 298 297 msleep(delay); \ 298 + } while (0) 299 + 300 + #define mipi_dsi_usleep_range(ctx, min, max) \ 301 + do { \ 302 + if (!(ctx)->accum_err) \ 303 + usleep_range(min, max); \ 299 304 } while (0) 300 305 301 306 /**
+4
include/drm/ttm/ttm_bo.h
··· 39 39 #include "ttm_device.h" 40 40 41 41 /* Default number of pre-faulted pages in the TTM fault handler */ 42 + #if CONFIG_PGTABLE_LEVELS > 2 43 + #define TTM_BO_VM_NUM_PREFAULT (1 << (PMD_SHIFT - PAGE_SHIFT)) 44 + #else 42 45 #define TTM_BO_VM_NUM_PREFAULT 16 46 + #endif 43 47 44 48 struct iosys_map; 45 49
+4 -2
lib/fonts/Kconfig
··· 105 105 106 106 config FONT_SUN12x22 107 107 bool "Sparc console 12x22 font (not supported by all drivers)" 108 - depends on (FRAMEBUFFER_CONSOLE && (!SPARC && FONTS || SPARC)) || DRM_PANIC 108 + depends on FRAMEBUFFER_CONSOLE || DRM_PANIC 109 + depends on !SPARC && FONTS 109 110 help 110 111 This is the high resolution console font for Sun machines with very 111 112 big letters (like the letters used in the SPARC PROM). If the ··· 114 113 115 114 config FONT_TER16x32 116 115 bool "Terminus 16x32 font (not supported by all drivers)" 117 - depends on (FRAMEBUFFER_CONSOLE && (!SPARC && FONTS || SPARC)) || DRM_PANIC 116 + depends on FRAMEBUFFER_CONSOLE || DRM_PANIC 117 + depends on !SPARC && FONTS || SPARC 118 118 help 119 119 Terminus Font is a clean, fixed width bitmap font, designed 120 120 for long (8 and more hours per day) work with computers.