diff --git a/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml b/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml index 0c85894648d8..84d68b8cfccc 100644 --- a/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml +++ b/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml @@ -71,6 +71,10 @@ properties: - const: iahb - const: venci + power-domains: + maxItems: 1 + description: phandle to the associated power domain + resets: minItems: 3 @@ -129,6 +133,7 @@ examples: reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy"; clocks = <&clk_isfr>, <&clk_iahb>, <&clk_venci>; clock-names = "isfr", "iahb", "venci"; + power-domains = <&pd_vpu>; #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml index 4b7e54a8f037..33481381cccc 100644 --- a/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml +++ b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml @@ -45,6 +45,19 @@ properties: - const: isfr additionalItems: true + ddc-i2c-bus: + $ref: /schemas/types.yaml#/definitions/phandle + deprecated: true + description: + The HDMI DDC bus can be connected to either a system I2C master or the + functionally-reduced I2C master contained in the DWC HDMI. When connected + to a system I2C master this property contains a phandle to that I2C + master controller. + + This property is deprecated, the system I2C master controller should + be referenced through the ddc-i2c-bus property of the HDMI connector + node. + interrupts: maxItems: 1 diff --git a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml index ae894d996d21..2ad0cd6dd49e 100644 --- a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml +++ b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml @@ -25,8 +25,8 @@ properties: reg: enum: - - 0x68 - 0x0f + - 0x68 description: | i2c address of the bridge, 0x68 or 0x0f, depending on bootstrap pins diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx6-hdmi.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx6-hdmi.yaml index 7979cf07f119..180c4b510fb1 100644 --- a/Documentation/devicetree/bindings/display/imx/fsl,imx6-hdmi.yaml +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx6-hdmi.yaml @@ -31,14 +31,6 @@ properties: clock-names: maxItems: 2 - ddc-i2c-bus: - $ref: /schemas/types.yaml#/definitions/phandle - description: - The HDMI DDC bus can be connected to either a system I2C master or the - functionally-reduced I2C master contained in the DWC HDMI. When connected - to a system I2C master this property contains a phandle to that I2C - master controller. - gpr: $ref: /schemas/types.yaml#/definitions/phandle description: diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9806e.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9806e.yaml new file mode 100644 index 000000000000..cfd7cc9c8725 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9806e.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/ilitek,ili9806e.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ilitek ILI9806E based MIPI-DSI panels + +maintainers: + - Michael Walle + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + items: + - enum: + - ortustech,com35h3p70ulc + - const: ilitek,ili9806e + + reg: + maxItems: 1 + + vdd-supply: true + vccio-supply: true + +required: + - compatible + - reg + - vdd-supply + - vccio-supply + - reset-gpios + - backlight + - port + +unevaluatedProperties: false + +examples: + - | + #include + + dsi { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "ortustech,com35h3p70ulc", "ilitek,ili9806e"; + reg = <0>; + vdd-supply = <®_vdd_panel>; + vccio-supply = <®_vccio_panel>; + reset-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>; + backlight = <&backlight>; + + port { + panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml index db5acd2807ed..9b92a05791cc 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml @@ -46,6 +46,8 @@ properties: - lg,ld070wx3-sl01 # LG Corporation 5" HD TFT LCD panel - lg,lh500wx1-sd03 + # Lincoln LCD197 5" 1080x1920 LCD panel + - lincolntech,lcd197 # One Stop Displays OSD101T2587-53TS 10.1" 1920x1200 panel - osddisplays,osd101t2587-53ts # Panasonic 10" WUXGA TFT LCD panel diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml index 2aac62219ff6..9d096856a79a 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml @@ -70,14 +70,6 @@ properties: - vpll - ref - ddc-i2c-bus: - $ref: /schemas/types.yaml#/definitions/phandle - description: - The HDMI DDC bus can be connected to either a system I2C master or the - functionally-reduced I2C master contained in the DWC HDMI. When connected - to a system I2C master this property contains a phandle to that I2C - master controller. - phys: maxItems: 1 description: The HDMI PHY diff --git a/MAINTAINERS b/MAINTAINERS index 082483b40fac..3997f9f1cbc8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6899,6 +6899,11 @@ S: Maintained F: Documentation/devicetree/bindings/display/panel/ilitek,ili9805.yaml F: drivers/gpu/drm/panel/panel-ilitek-ili9805.c +DRM DRIVER FOR ILITEK ILI9806E PANELS +M: Michael Walle +S: Maintained +F: drivers/gpu/drm/panel/panel-ilitek-ili9806e.c + DRM DRIVER FOR JADARD JD9365DA-H3 MIPI-DSI LCD PANELS M: Jagan Teki S: Maintained @@ -7519,8 +7524,9 @@ F: include/uapi/drm/v3d_drm.h DRM DRIVERS FOR VC4 M: Maxime Ripard +M: Dave Stevenson +R: Raspberry Pi Kernel Maintenance S: Supported -T: git git://github.com/anholt/linux T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: Documentation/devicetree/bindings/display/brcm,bcm2835-*.yaml F: drivers/gpu/drm/vc4/ diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index f5c989aed7e9..6dd0016fc9cd 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -108,7 +108,6 @@ config DRM_KMS_HELPER config DRM_PANIC bool "Display a user-friendly message when a kernel panic occurs" depends on DRM && !(FRAMEBUFFER_CONSOLE && VT_CONSOLE) - select DRM_KMS_HELPER select FONT_SUPPORT help Enable a drm panic handler, which will display a user-friendly message @@ -138,7 +137,7 @@ config DRM_PANIC_DEBUG If in doubt, say "N". config DRM_PANIC_SCREEN - string "Panic screen formater" + string "Panic screen formatter" default "user" depends on DRM_PANIC help @@ -248,6 +247,7 @@ config DRM_TTM_KUNIT_TEST default n depends on DRM && KUNIT && MMU && (UML || COMPILE_TEST) select DRM_TTM + select DRM_BUDDY select DRM_EXPORT_FOR_TESTS if m select DRM_KUNIT_TEST_HELPERS default KUNIT_ALL_TESTS diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 6695af70768f..2fd9c78eab73 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -45,7 +45,6 @@ #include #include #include -#include #include "ast_ddc.h" #include "ast_drv.h" @@ -1358,6 +1357,14 @@ static int ast_crtc_init(struct drm_device *dev) return 0; } +/* + * VGA Encoder + */ + +static const struct drm_encoder_funcs ast_vga_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + /* * VGA Connector */ @@ -1411,7 +1418,8 @@ static int ast_vga_output_init(struct ast_device *ast) struct drm_connector *connector = &ast->output.vga.connector; int ret; - ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC); + ret = drm_encoder_init(dev, encoder, &ast_vga_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); if (ret) return ret; encoder->possible_crtcs = drm_crtc_mask(crtc); @@ -1427,6 +1435,14 @@ static int ast_vga_output_init(struct ast_device *ast) return 0; } +/* + * SIL164 Encoder + */ + +static const struct drm_encoder_funcs ast_sil164_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + /* * SIL164 Connector */ @@ -1480,7 +1496,8 @@ static int ast_sil164_output_init(struct ast_device *ast) struct drm_connector *connector = &ast->output.sil164.connector; int ret; - ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS); + ret = drm_encoder_init(dev, encoder, &ast_sil164_encoder_funcs, + DRM_MODE_ENCODER_TMDS, NULL); if (ret) return ret; encoder->possible_crtcs = drm_crtc_mask(crtc); @@ -1496,6 +1513,14 @@ static int ast_sil164_output_init(struct ast_device *ast) return 0; } +/* + * DP501 Encoder + */ + +static const struct drm_encoder_funcs ast_dp501_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + /* * DP501 Connector */ @@ -1578,7 +1603,8 @@ static int ast_dp501_output_init(struct ast_device *ast) struct drm_connector *connector = &ast->output.dp501.connector; int ret; - ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS); + ret = drm_encoder_init(dev, encoder, &ast_dp501_encoder_funcs, + DRM_MODE_ENCODER_TMDS, NULL); if (ret) return ret; encoder->possible_crtcs = drm_crtc_mask(crtc); @@ -1594,6 +1620,14 @@ static int ast_dp501_output_init(struct ast_device *ast) return 0; } +/* + * ASPEED Display-Port Encoder + */ + +static const struct drm_encoder_funcs ast_astdp_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + /* * ASPEED Display-Port Connector */ @@ -1688,7 +1722,8 @@ static int ast_astdp_output_init(struct ast_device *ast) struct drm_connector *connector = &ast->output.astdp.connector; int ret; - ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS); + ret = drm_encoder_init(dev, encoder, &ast_astdp_encoder_funcs, + DRM_MODE_ENCODER_TMDS, NULL); if (ret) return ret; encoder->possible_crtcs = drm_crtc_mask(crtc); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index b5dbff21c187..ddf1e4424ffd 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -41,10 +41,8 @@ struct bridge_init { struct device_node *node; }; -static int analogix_dp_init_dp(struct analogix_dp_device *dp) +static void analogix_dp_init_dp(struct analogix_dp_device *dp) { - int ret; - analogix_dp_reset(dp); analogix_dp_swreset(dp); @@ -56,13 +54,9 @@ static int analogix_dp_init_dp(struct analogix_dp_device *dp) analogix_dp_enable_sw_function(dp); analogix_dp_config_interrupt(dp); - ret = analogix_dp_init_analog_func(dp); - if (ret) - return ret; analogix_dp_init_hpd(dp); analogix_dp_init_aux(dp); - return 0; } static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) @@ -237,7 +231,7 @@ static int analogix_dp_training_pattern_dis(struct analogix_dp_device *dp) static int analogix_dp_link_start(struct analogix_dp_device *dp) { u8 buf[4]; - int lane, lane_count, pll_tries, retval; + int lane, lane_count, retval; lane_count = dp->link_train.lane_count; @@ -249,6 +243,16 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp) /* Set link rate and count as you want to establish*/ analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); + retval = analogix_dp_wait_pll_locked(dp); + if (retval) { + DRM_DEV_ERROR(dp->dev, "Wait for pll lock failed %d\n", retval); + return retval; + } + /* + * MACRO_RST must be applied after the PLL_LOCK to avoid + * the DP inter pair skew issue for at least 10 us + */ + analogix_dp_reset_macro(dp); analogix_dp_set_lane_count(dp, dp->link_train.lane_count); /* Setup RX configuration */ @@ -271,18 +275,6 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp) DP_TRAIN_PRE_EMPH_LEVEL_0; analogix_dp_set_lane_link_training(dp); - /* Wait for PLL lock */ - pll_tries = 0; - while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { - if (pll_tries == DP_TIMEOUT_LOOP_COUNT) { - dev_err(dp->dev, "Wait for PLL lock timed out\n"); - return -ETIMEDOUT; - } - - pll_tries++; - usleep_range(90, 120); - } - /* Set training pattern 1 */ analogix_dp_set_training_pattern(dp, TRAINING_PTN1); @@ -568,12 +560,6 @@ static int analogix_dp_full_link_train(struct analogix_dp_device *dp, int retval = 0; bool training_finished = false; - /* - * MACRO_RST must be applied after the PLL_LOCK to avoid - * the DP inter pair skew issue for at least 10 us - */ - analogix_dp_reset_macro(dp); - /* Initialize by reading RX's DPCD */ analogix_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); @@ -638,22 +624,22 @@ static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) { int ret; u8 link_align, link_status[2]; - enum pll_status status; - - analogix_dp_reset_macro(dp); analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); - analogix_dp_set_lane_count(dp, dp->link_train.lane_count); - analogix_dp_set_lane_link_training(dp); - - ret = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status, - status != PLL_UNLOCKED, 120, - 120 * DP_TIMEOUT_LOOP_COUNT); + ret = analogix_dp_wait_pll_locked(dp); if (ret) { DRM_DEV_ERROR(dp->dev, "Wait for pll lock failed %d\n", ret); return ret; } + /* + * MACRO_RST must be applied after the PLL_LOCK to avoid + * the DP inter pair skew issue for at least 10 us + */ + analogix_dp_reset_macro(dp); + analogix_dp_set_lane_count(dp, dp->link_train.lane_count); + analogix_dp_set_lane_link_training(dp); + /* source Set training pattern 1 */ analogix_dp_set_training_pattern(dp, TRAINING_PTN1); /* From DP spec, pattern must be on-screen for a minimum 500us */ @@ -723,11 +709,6 @@ static int analogix_dp_config_video(struct analogix_dp_device *dp) analogix_dp_set_video_color_format(dp); - if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { - dev_err(dp->dev, "PLL is not locked yet.\n"); - return -EINVAL; - } - for (;;) { timeout_loop++; if (analogix_dp_is_slave_video_stream_clock_on(dp) == 0) @@ -1251,20 +1232,9 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp) pm_runtime_get_sync(dp->dev); - ret = clk_prepare_enable(dp->clock); - if (ret < 0) { - DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret); - goto out_dp_clk_pre; - } - - if (dp->plat_data->power_on_start) - dp->plat_data->power_on_start(dp->plat_data); - - phy_power_on(dp->phy); - - ret = analogix_dp_init_dp(dp); + ret = analogix_dp_init_analog_func(dp); if (ret) - goto out_dp_init; + return ret; /* * According to DP spec v1.3 chap 3.5.1.2 Link Training, @@ -1283,18 +1253,10 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp) goto out_dp_init; } - if (dp->plat_data->power_on_end) - dp->plat_data->power_on_end(dp->plat_data); - enable_irq(dp->irq); return 0; out_dp_init: - phy_power_off(dp->phy); - if (dp->plat_data->power_off) - dp->plat_data->power_off(dp->plat_data); - clk_disable_unprepare(dp->clock); -out_dp_clk_pre: pm_runtime_put_sync(dp->dev); return ret; @@ -1357,13 +1319,7 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) disable_irq(dp->irq); - if (dp->plat_data->power_off) - dp->plat_data->power_off(dp->plat_data); - analogix_dp_set_analog_power_down(dp, POWER_ALL, 1); - phy_power_off(dp->phy); - - clk_disable_unprepare(dp->clock); pm_runtime_put_sync(dp->dev); @@ -1654,8 +1610,6 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data) return ERR_CAST(dp->clock); } - clk_prepare_enable(dp->clock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dp->reg_base = devm_ioremap_resource(&pdev->dev, res); @@ -1717,6 +1671,40 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data) } EXPORT_SYMBOL_GPL(analogix_dp_probe); +int analogix_dp_suspend(struct analogix_dp_device *dp) +{ + phy_power_off(dp->phy); + + if (dp->plat_data->power_off) + dp->plat_data->power_off(dp->plat_data); + + clk_disable_unprepare(dp->clock); + + return 0; +} +EXPORT_SYMBOL_GPL(analogix_dp_suspend); + +int analogix_dp_resume(struct analogix_dp_device *dp) +{ + int ret; + + ret = clk_prepare_enable(dp->clock); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret); + return ret; + } + + if (dp->plat_data->power_on) + dp->plat_data->power_on(dp->plat_data); + + phy_power_on(dp->phy); + + analogix_dp_init_dp(dp); + + return 0; +} +EXPORT_SYMBOL_GPL(analogix_dp_resume); + int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev) { int ret; @@ -1724,31 +1712,44 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev) dp->drm_dev = drm_dev; dp->encoder = dp->plat_data->encoder; + if (IS_ENABLED(CONFIG_PM)) { + pm_runtime_use_autosuspend(dp->dev); + pm_runtime_set_autosuspend_delay(dp->dev, 100); + pm_runtime_enable(dp->dev); + } else { + ret = analogix_dp_resume(dp); + if (ret) + return ret; + } + dp->aux.name = "DP-AUX"; dp->aux.transfer = analogix_dpaux_transfer; dp->aux.dev = dp->dev; dp->aux.drm_dev = drm_dev; ret = drm_dp_aux_register(&dp->aux); - if (ret) - return ret; - - pm_runtime_use_autosuspend(dp->dev); - pm_runtime_set_autosuspend_delay(dp->dev, 100); - pm_runtime_enable(dp->dev); + if (ret) { + DRM_ERROR("failed to register AUX (%d)\n", ret); + goto err_disable_pm_runtime; + } ret = analogix_dp_create_bridge(drm_dev, dp); if (ret) { DRM_ERROR("failed to create bridge (%d)\n", ret); - goto err_disable_pm_runtime; + goto err_unregister_aux; } return 0; -err_disable_pm_runtime: - pm_runtime_dont_use_autosuspend(dp->dev); - pm_runtime_disable(dp->dev); +err_unregister_aux: drm_dp_aux_unregister(&dp->aux); +err_disable_pm_runtime: + if (IS_ENABLED(CONFIG_PM)) { + pm_runtime_dont_use_autosuspend(dp->dev); + pm_runtime_disable(dp->dev); + } else { + analogix_dp_suspend(dp); + } return ret; } @@ -1765,40 +1766,16 @@ void analogix_dp_unbind(struct analogix_dp_device *dp) } drm_dp_aux_unregister(&dp->aux); - pm_runtime_dont_use_autosuspend(dp->dev); - pm_runtime_disable(dp->dev); + + if (IS_ENABLED(CONFIG_PM)) { + pm_runtime_dont_use_autosuspend(dp->dev); + pm_runtime_disable(dp->dev); + } else { + analogix_dp_suspend(dp); + } } EXPORT_SYMBOL_GPL(analogix_dp_unbind); -void analogix_dp_remove(struct analogix_dp_device *dp) -{ - clk_disable_unprepare(dp->clock); -} -EXPORT_SYMBOL_GPL(analogix_dp_remove); - -#ifdef CONFIG_PM -int analogix_dp_suspend(struct analogix_dp_device *dp) -{ - clk_disable_unprepare(dp->clock); - return 0; -} -EXPORT_SYMBOL_GPL(analogix_dp_suspend); - -int analogix_dp_resume(struct analogix_dp_device *dp) -{ - int ret; - - ret = clk_prepare_enable(dp->clock); - if (ret < 0) { - DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret); - return ret; - } - - return 0; -} -EXPORT_SYMBOL_GPL(analogix_dp_resume); -#endif - int analogix_dp_start_crc(struct drm_connector *connector) { struct analogix_dp_device *dp = to_dp(connector); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 382b2f068ab9..774d11574b09 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -95,11 +95,6 @@ enum dynamic_range { CEA }; -enum pll_status { - PLL_UNLOCKED, - PLL_LOCKED -}; - enum clock_recovery_m_value_type { CALCULATED_M, REGISTER_M @@ -191,7 +186,7 @@ void analogix_dp_swreset(struct analogix_dp_device *dp); void analogix_dp_config_interrupt(struct analogix_dp_device *dp); void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp); void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp); -enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp); +int analogix_dp_wait_pll_locked(struct analogix_dp_device *dp); void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable); void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, enum analog_power_block block, diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index d267cf05cbca..3afc73c858c4 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -217,15 +217,13 @@ void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp) writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK); } -enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp) +int analogix_dp_wait_pll_locked(struct analogix_dp_device *dp) { - u32 reg; + u32 val; - reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL); - if (reg & PLL_LOCK) - return PLL_LOCKED; - else - return PLL_UNLOCKED; + return readl_poll_timeout(dp->reg_base + ANALOGIX_DP_DEBUG_CTL, val, + val & PLL_LOCK, 120, + 120 * DP_TIMEOUT_LOOP_COUNT); } void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable) @@ -356,7 +354,6 @@ void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, int analogix_dp_init_analog_func(struct analogix_dp_device *dp) { u32 reg; - int timeout_loop = 0; analogix_dp_set_analog_power_down(dp, POWER_ALL, 0); @@ -368,18 +365,7 @@ int analogix_dp_init_analog_func(struct analogix_dp_device *dp) writel(reg, dp->reg_base + ANALOGIX_DP_DEBUG_CTL); /* Power up PLL */ - if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { - analogix_dp_set_pll_power_down(dp, 0); - - while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { - timeout_loop++; - if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { - dev_err(dp->dev, "failed to get pll lock status\n"); - return -ETIMEDOUT; - } - usleep_range(10, 20); - } - } + analogix_dp_set_pll_power_down(dp, 0); /* Enable Serdes FIFO function and Link symbol clock domain module */ reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); @@ -938,7 +924,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, struct drm_dp_aux_msg *msg) { u32 reg; - u32 status_reg; u8 *buffer = msg->buffer; unsigned int i; int ret; @@ -1025,12 +1010,17 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, /* Clear interrupt source for AUX CH access error */ reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); - status_reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA); - if ((reg & AUX_ERR) || (status_reg & AUX_STATUS_MASK)) { + if ((reg & AUX_ERR)) { + u32 aux_status = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA) & + AUX_STATUS_MASK; + writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA); + if (aux_status == AUX_STATUS_TIMEOUT_ERROR) + return -ETIMEDOUT; + dev_warn(dp->dev, "AUX CH error happened: %#x (%d)\n", - status_reg & AUX_STATUS_MASK, !!(reg & AUX_ERR)); + aux_status, !!(reg & AUX_ERR)); goto aux_error; } diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h index e284ee8da58b..12735139046c 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h @@ -361,6 +361,15 @@ /* ANALOGIX_DP_AUX_CH_STA */ #define AUX_BUSY (0x1 << 4) #define AUX_STATUS_MASK (0xf << 0) +#define AUX_STATUS_OK (0x0 << 0) +#define AUX_STATUS_NACK_ERROR (0x1 << 0) +#define AUX_STATUS_TIMEOUT_ERROR (0x2 << 0) +#define AUX_STATUS_UNKNOWN_ERROR (0x3 << 0) +#define AUX_STATUS_MUCH_DEFER_ERROR (0x4 << 0) +#define AUX_STATUS_TX_SHORT_ERROR (0x5 << 0) +#define AUX_STATUS_RX_SHORT_ERROR (0x6 << 0) +#define AUX_STATUS_NACK_WITHOUT_M_ERROR (0x7 << 0) +#define AUX_STATUS_I2C_NACK_ERROR (0x8 << 0) /* ANALOGIX_DP_AUX_CH_DEFER_CTL */ #define DEFER_CTRL_EN (0x1 << 7) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 87c7346d037e..b8b7a227addf 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -382,9 +382,6 @@ struct tc_data { /* HPD pin number (0 or 1) or -ENODEV */ int hpd_pin; - - /* Number of pixels to subtract from a line due to pixel clock delta */ - u32 line_pixel_subtract; }; static inline struct tc_data *aux_to_tc(struct drm_dp_aux *a) @@ -580,14 +577,9 @@ static int tc_pllupdate(struct tc_data *tc, unsigned int pllctrl) return 0; } -static u32 div64_round_up(u64 v, u32 d) +static int tc_pxl_pll_calc(struct tc_data *tc, u32 refclk, u32 pixelclock, + int *out_best_pixelclock, u32 *out_pxl_pllparam) { - return div_u64(v + d - 1, d); -} - -static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) -{ - int ret; int i_pre, best_pre = 1; int i_post, best_post = 1; int div, best_div = 1; @@ -666,11 +658,7 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) return -EINVAL; } - tc->line_pixel_subtract = tc->mode.htotal - - div64_round_up(tc->mode.htotal * (u64)best_pixelclock, pixelclock); - - dev_dbg(tc->dev, "PLL: got %d, delta %d (subtract %d px)\n", best_pixelclock, - best_delta, tc->line_pixel_subtract); + dev_dbg(tc->dev, "PLL: got %d, delta %d\n", best_pixelclock, best_delta); dev_dbg(tc->dev, "PLL: %d / %d / %d * %d / %d\n", refclk, ext_div[best_pre], best_div, best_mul, ext_div[best_post]); @@ -683,11 +671,6 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) if (best_mul == 128) best_mul = 0; - /* Power up PLL and switch to bypass */ - ret = regmap_write(tc->regmap, PXL_PLLCTRL, PLLBYP | PLLEN); - if (ret) - return ret; - pxl_pllparam = vco_hi << 24; /* For PLL VCO >= 300 MHz = 1 */ pxl_pllparam |= ext_div[best_pre] << 20; /* External Pre-divider */ pxl_pllparam |= ext_div[best_post] << 16; /* External Post-divider */ @@ -695,6 +678,29 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) pxl_pllparam |= best_div << 8; /* Divider for PLL RefClk */ pxl_pllparam |= best_mul; /* Multiplier for PLL */ + if (out_best_pixelclock) + *out_best_pixelclock = best_pixelclock; + + if (out_pxl_pllparam) + *out_pxl_pllparam = pxl_pllparam; + + return 0; +} + +static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) +{ + u32 pxl_pllparam = 0; + int ret; + + ret = tc_pxl_pll_calc(tc, refclk, pixelclock, NULL, &pxl_pllparam); + if (ret) + return ret; + + /* Power up PLL and switch to bypass */ + ret = regmap_write(tc->regmap, PXL_PLLCTRL, PLLBYP | PLLEN); + if (ret) + return ret; + ret = regmap_write(tc->regmap, PXL_PLLPARAM, pxl_pllparam); if (ret) return ret; @@ -732,7 +738,7 @@ static int tc_stream_clock_calc(struct tc_data *tc) static int tc_set_syspllparam(struct tc_data *tc) { unsigned long rate; - u32 pllparam = SYSCLK_SEL_LSCLK | LSCLK_DIV_2; + u32 pllparam = SYSCLK_SEL_LSCLK | LSCLK_DIV_1; rate = clk_get_rate(tc->refclk); switch (rate) { @@ -896,13 +902,6 @@ static int tc_set_common_video_mode(struct tc_data *tc, upper_margin, lower_margin, vsync_len); dev_dbg(tc->dev, "total: %dx%d\n", mode->htotal, mode->vtotal); - if (right_margin > tc->line_pixel_subtract) { - right_margin -= tc->line_pixel_subtract; - } else { - dev_err(tc->dev, "Bridge pixel clock too slow for mode\n"); - right_margin = 0; - } - /* * LCD Ctl Frame Size * datasheet is not clear of vsdelay in case of DPI @@ -1357,10 +1356,10 @@ static int tc_dsi_rx_enable(struct tc_data *tc) u32 value; int ret; - regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 25); - regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 25); - regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 25); - regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 25); + regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 5); + regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 5); + regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 5); + regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 5); regmap_write(tc->regmap, PPI_D0S_ATMR, 0); regmap_write(tc->regmap, PPI_D1S_ATMR, 0); regmap_write(tc->regmap, PPI_TX_RX_TA, TTA_GET | TTA_SURE); @@ -1606,6 +1605,18 @@ static int tc_dpi_atomic_check(struct drm_bridge *bridge, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { + struct tc_data *tc = bridge_to_tc(bridge); + int adjusted_clock = 0; + int ret; + + ret = tc_pxl_pll_calc(tc, clk_get_rate(tc->refclk), + crtc_state->mode.clock * 1000, + &adjusted_clock, NULL); + if (ret) + return ret; + + crtc_state->adjusted_mode.clock = adjusted_clock / 1000; + /* DSI->DPI interface clock limitation: upto 100 MHz */ if (crtc_state->adjusted_mode.clock > 100000) return -EINVAL; @@ -1618,6 +1629,18 @@ static int tc_edp_atomic_check(struct drm_bridge *bridge, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { + struct tc_data *tc = bridge_to_tc(bridge); + int adjusted_clock = 0; + int ret; + + ret = tc_pxl_pll_calc(tc, clk_get_rate(tc->refclk), + crtc_state->mode.clock * 1000, + &adjusted_clock, NULL); + if (ret) + return ret; + + crtc_state->adjusted_mode.clock = adjusted_clock / 1000; + /* DPI->(e)DP interface clock limitation: upto 154 MHz */ if (crtc_state->adjusted_mode.clock > 154000) return -EINVAL; @@ -1820,6 +1843,7 @@ static void tc_edp_bridge_detach(struct drm_bridge *bridge) } #define MAX_INPUT_SEL_FORMATS 1 +#define MAX_OUTPUT_SEL_FORMATS 1 static u32 * tc_dpi_atomic_get_input_bus_fmts(struct drm_bridge *bridge, @@ -1845,6 +1869,28 @@ tc_dpi_atomic_get_input_bus_fmts(struct drm_bridge *bridge, return input_fmts; } +static u32 * +tc_edp_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + unsigned int *num_output_fmts) +{ + u32 *output_fmts; + + *num_output_fmts = 0; + + output_fmts = kcalloc(MAX_OUTPUT_SEL_FORMATS, sizeof(*output_fmts), + GFP_KERNEL); + if (!output_fmts) + return NULL; + + output_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; + *num_output_fmts = 1; + + return output_fmts; +} + static const struct drm_bridge_funcs tc_dpi_bridge_funcs = { .attach = tc_dpi_bridge_attach, .mode_valid = tc_dpi_mode_valid, @@ -1871,6 +1917,8 @@ static const struct drm_bridge_funcs tc_edp_bridge_funcs = { .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt, + .atomic_get_output_bus_fmts = tc_edp_atomic_get_output_bus_fmts, }; static bool tc_readable_reg(struct device *dev, unsigned int reg) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index 2dab3ad8ce64..7854820089ec 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -716,7 +716,7 @@ drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *co EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_audio_infoframe); /** - * drm_atomic_helper_connector_hdmi_disable_audio_infoframe - Stop sending the Audio Infoframe + * drm_atomic_helper_connector_hdmi_clear_audio_infoframe - Stop sending the Audio Infoframe * @connector: A pointer to the HDMI connector * * This function is meant for HDMI connector drivers to stop sending their @@ -727,7 +727,7 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_audio_infoframe); * Zero on success, error code on failure. */ int -drm_atomic_helper_connector_hdmi_disable_audio_infoframe(struct drm_connector *connector) +drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *connector) { struct drm_connector_hdmi_infoframe *infoframe = &connector->hdmi.infoframes.audio; @@ -749,4 +749,4 @@ drm_atomic_helper_connector_hdmi_disable_audio_infoframe(struct drm_connector *c return ret; } -EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_disable_audio_infoframe); +EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_clear_audio_infoframe); diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c index 293d4dcbc80d..948aed00595e 100644 --- a/drivers/gpu/drm/drm_panic.c +++ b/drivers/gpu/drm/drm_panic.c @@ -7,16 +7,19 @@ */ #include +#include #include #include #include +#include #include +#include #include +#include #include #include #include -#include #include #include #include @@ -78,7 +81,7 @@ static struct drm_panic_line panic_msg[] = { PANIC_LINE("Please reboot your computer."), }; -static const struct drm_panic_line logo[] = { +static const struct drm_panic_line logo_ascii[] = { PANIC_LINE(" .--. _"), PANIC_LINE(" |o_o | | |"), PANIC_LINE(" |:_/ | | |"), @@ -88,6 +91,42 @@ static const struct drm_panic_line logo[] = { PANIC_LINE(" \\___)=(___/"), }; +#if defined(CONFIG_LOGO) && !defined(MODULE) +static const struct linux_logo *logo_mono; + +static int drm_panic_setup_logo(void) +{ + const struct linux_logo *logo = fb_find_logo(1); + const unsigned char *logo_data; + struct linux_logo *logo_dup; + + if (!logo || logo->type != LINUX_LOGO_MONO) + return 0; + + /* The logo is __init, so we must make a copy for later use */ + logo_data = kmemdup(logo->data, + size_mul(DIV_ROUND_UP(logo->width, BITS_PER_BYTE), logo->height), + GFP_KERNEL); + if (!logo_data) + return -ENOMEM; + + logo_dup = kmemdup(logo, sizeof(*logo), GFP_KERNEL); + if (!logo_dup) { + kfree(logo_data); + return -ENOMEM; + } + + logo_dup->data = logo_data; + logo_mono = logo_dup; + + return 0; +} + +device_initcall(drm_panic_setup_logo); +#else +#define logo_mono ((const struct linux_logo *)NULL) +#endif + /* * Color conversion */ @@ -447,20 +486,27 @@ static void draw_txt_rectangle(struct drm_scanout_buffer *sb, static void draw_panic_static_user(struct drm_scanout_buffer *sb) { size_t msg_lines = ARRAY_SIZE(panic_msg); - size_t logo_lines = ARRAY_SIZE(logo); + size_t logo_ascii_lines = ARRAY_SIZE(logo_ascii); u32 fg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_FOREGROUND_COLOR, sb->format->format); u32 bg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_BACKGROUND_COLOR, sb->format->format); const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL); struct drm_rect r_screen, r_logo, r_msg; + unsigned int logo_width, logo_height; if (!font) return; r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height); - r_logo = DRM_RECT_INIT(0, 0, - get_max_line_len(logo, logo_lines) * font->width, - logo_lines * font->height); + if (logo_mono) { + logo_width = logo_mono->width; + logo_height = logo_mono->height; + } else { + logo_width = get_max_line_len(logo_ascii, logo_ascii_lines) * font->width; + logo_height = logo_ascii_lines * font->height; + } + + r_logo = DRM_RECT_INIT(0, 0, logo_width, logo_height); r_msg = DRM_RECT_INIT(0, 0, min(get_max_line_len(panic_msg, msg_lines) * font->width, sb->width), min(msg_lines * font->height, sb->height)); @@ -471,9 +517,14 @@ static void draw_panic_static_user(struct drm_scanout_buffer *sb) /* Fill with the background color, and draw text on top */ drm_panic_fill(sb, &r_screen, bg_color); - if ((r_msg.x1 >= drm_rect_width(&r_logo) || r_msg.y1 >= drm_rect_height(&r_logo)) && - drm_rect_width(&r_logo) < sb->width && drm_rect_height(&r_logo) < sb->height) { - draw_txt_rectangle(sb, font, logo, logo_lines, false, &r_logo, fg_color); + if ((r_msg.x1 >= logo_width || r_msg.y1 >= logo_height) && + logo_width <= sb->width && logo_height <= sb->height) { + if (logo_mono) + drm_panic_blit(sb, &r_logo, logo_mono->data, DIV_ROUND_UP(logo_width, 8), + fg_color); + else + draw_txt_rectangle(sb, font, logo_ascii, logo_ascii_lines, false, &r_logo, + fg_color); } draw_txt_rectangle(sb, font, panic_msg, msg_lines, true, &r_msg, fg_color); } @@ -582,7 +633,7 @@ static void draw_panic_dispatch(struct drm_scanout_buffer *sb) static void draw_panic_plane(struct drm_plane *plane) { - struct drm_scanout_buffer sb; + struct drm_scanout_buffer sb = { }; int ret; unsigned long flags; diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c index f48c4343f469..097f8c4617de 100644 --- a/drivers/gpu/drm/exynos/exynos_dp.c +++ b/drivers/gpu/drm/exynos/exynos_dp.c @@ -233,7 +233,7 @@ static int exynos_dp_probe(struct platform_device *pdev) /* The remote port can be either a panel or a bridge */ dp->plat_data.panel = panel; dp->plat_data.dev_type = EXYNOS_DP; - dp->plat_data.power_on_start = exynos_dp_poweron; + dp->plat_data.power_on = exynos_dp_poweron; dp->plat_data.power_off = exynos_dp_poweroff; dp->plat_data.attach = exynos_dp_bridge_attach; dp->plat_data.get_modes = exynos_dp_get_modes; @@ -251,10 +251,7 @@ static int exynos_dp_probe(struct platform_device *pdev) static void exynos_dp_remove(struct platform_device *pdev) { - struct exynos_dp_device *dp = platform_get_drvdata(pdev); - component_del(&pdev->dev, &exynos_dp_ops); - analogix_dp_remove(dp->adp); } static int exynos_dp_suspend(struct device *dev) diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig index 96cbe020f493..d6449ebae838 100644 --- a/drivers/gpu/drm/mediatek/Kconfig +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -7,6 +7,7 @@ config DRM_MEDIATEK depends on HAVE_ARM_SMCCC depends on OF depends on MTK_MMSYS + select DRM_GEM_DMA_HELPER if DRM_FBDEV_EMULATION select DRM_KMS_HELPER select DRM_MIPI_DSI select DRM_PANEL diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index bf4eadfe21cb..9f49b0189d3b 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -205,6 +205,15 @@ config DRM_PANEL_ILITEK_ILI9805 Say Y if you want to enable support for panels based on the Ilitek ILI9805 controller. +config DRM_PANEL_ILITEK_ILI9806E + tristate "Ilitek ILI9806E-based panels" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y if you want to enable support for panels based on the + Ilitek ILI9806E controller. + config DRM_PANEL_ILITEK_ILI9881C tristate "Ilitek ILI9881C-based panels" depends on OF @@ -328,6 +337,17 @@ config DRM_PANEL_LEADTEK_LTK500HD1829 24 bit RGB per pixel. It provides a MIPI DSI interface to the host and has a built-in LED backlight. +config DRM_PANEL_LINCOLNTECH_LCD197 + tristate "Lincoln Technologies lcd197 panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for lincolntech lcd197 + TFT-LCD modules. The panel has a 1080x1920 resolution and uses + 24 bit RGB per pixel. It provides a MIPI DSI interface to + the host. + config DRM_PANEL_LG_LB035Q02 tristate "LG LB035Q024573 RGB panel" depends on GPIOLIB && OF && SPI diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 051b75b3df7b..5581387707c6 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_DRM_PANEL_HIMAX_HX8394) += panel-himax-hx8394.o obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9805) += panel-ilitek-ili9805.o +obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9806E) += panel-ilitek-ili9806e.o obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9882T) += panel-ilitek-ili9882t.o obj-$(CONFIG_DRM_PANEL_INNOLUX_EJ030NA) += panel-innolux-ej030na.o @@ -33,6 +34,7 @@ obj-$(CONFIG_DRM_PANEL_KHADAS_TS050) += panel-khadas-ts050.o obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o +obj-$(CONFIG_DRM_PANEL_LINCOLNTECH_LCD197) += panel-lincolntech-lcd197.o obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o obj-$(CONFIG_DRM_PANEL_LG_SW43408) += panel-lg-sw43408.o diff --git a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c index bcaa63d1955f..b05a663c134c 100644 --- a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c +++ b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c @@ -33,119 +33,97 @@ static void tm5p5_nt35596_reset(struct tm5p5_nt35596 *ctx) usleep_range(15000, 16000); } -static int tm5p5_nt35596_on(struct tm5p5_nt35596 *ctx) +static void tm5p5_nt35596_on(struct mipi_dsi_multi_context *dsi_ctx) { - struct mipi_dsi_device *dsi = ctx->dsi; + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xff, 0x05); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfb, 0x01); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc5, 0x31); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xff, 0x04); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x01, 0x84); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x05, 0x25); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x06, 0x01); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x07, 0x20); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x08, 0x06); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x09, 0x08); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0a, 0x10); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0b, 0x10); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0c, 0x10); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0d, 0x14); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0e, 0x14); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0f, 0x14); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x10, 0x14); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x11, 0x14); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x12, 0x14); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x17, 0xf3); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0xc0); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x19, 0xc0); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1a, 0xc0); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1b, 0xb3); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1c, 0xb3); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1d, 0xb3); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1e, 0xb3); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1f, 0xb3); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x20, 0xb3); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfb, 0x01); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xff, 0x00); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfb, 0x01); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x35, 0x01); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd3, 0x06); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd4, 0x04); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x5e, 0x0d); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x11, 0x00); - mipi_dsi_generic_write_seq(dsi, 0xff, 0x05); - mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_generic_write_seq(dsi, 0xc5, 0x31); - mipi_dsi_generic_write_seq(dsi, 0xff, 0x04); - mipi_dsi_generic_write_seq(dsi, 0x01, 0x84); - mipi_dsi_generic_write_seq(dsi, 0x05, 0x25); - mipi_dsi_generic_write_seq(dsi, 0x06, 0x01); - mipi_dsi_generic_write_seq(dsi, 0x07, 0x20); - mipi_dsi_generic_write_seq(dsi, 0x08, 0x06); - mipi_dsi_generic_write_seq(dsi, 0x09, 0x08); - mipi_dsi_generic_write_seq(dsi, 0x0a, 0x10); - mipi_dsi_generic_write_seq(dsi, 0x0b, 0x10); - mipi_dsi_generic_write_seq(dsi, 0x0c, 0x10); - mipi_dsi_generic_write_seq(dsi, 0x0d, 0x14); - mipi_dsi_generic_write_seq(dsi, 0x0e, 0x14); - mipi_dsi_generic_write_seq(dsi, 0x0f, 0x14); - mipi_dsi_generic_write_seq(dsi, 0x10, 0x14); - mipi_dsi_generic_write_seq(dsi, 0x11, 0x14); - mipi_dsi_generic_write_seq(dsi, 0x12, 0x14); - mipi_dsi_generic_write_seq(dsi, 0x17, 0xf3); - mipi_dsi_generic_write_seq(dsi, 0x18, 0xc0); - mipi_dsi_generic_write_seq(dsi, 0x19, 0xc0); - mipi_dsi_generic_write_seq(dsi, 0x1a, 0xc0); - mipi_dsi_generic_write_seq(dsi, 0x1b, 0xb3); - mipi_dsi_generic_write_seq(dsi, 0x1c, 0xb3); - mipi_dsi_generic_write_seq(dsi, 0x1d, 0xb3); - mipi_dsi_generic_write_seq(dsi, 0x1e, 0xb3); - mipi_dsi_generic_write_seq(dsi, 0x1f, 0xb3); - mipi_dsi_generic_write_seq(dsi, 0x20, 0xb3); - mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_generic_write_seq(dsi, 0xff, 0x00); - mipi_dsi_generic_write_seq(dsi, 0xfb, 0x01); - mipi_dsi_generic_write_seq(dsi, 0x35, 0x01); - mipi_dsi_generic_write_seq(dsi, 0xd3, 0x06); - mipi_dsi_generic_write_seq(dsi, 0xd4, 0x04); - mipi_dsi_generic_write_seq(dsi, 0x5e, 0x0d); - mipi_dsi_generic_write_seq(dsi, 0x11, 0x00); - msleep(100); - mipi_dsi_generic_write_seq(dsi, 0x29, 0x00); - mipi_dsi_generic_write_seq(dsi, 0x53, 0x24); + mipi_dsi_msleep(dsi_ctx, 100); - return 0; + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x29, 0x00); + mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x53, 0x24); } -static int tm5p5_nt35596_off(struct tm5p5_nt35596 *ctx) +static void tm5p5_nt35596_off(struct mipi_dsi_multi_context *dsi_ctx) { - struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + mipi_dsi_dcs_set_display_off_multi(dsi_ctx); - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - msleep(60); + mipi_dsi_msleep(dsi_ctx, 60); - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } + mipi_dsi_dcs_enter_sleep_mode_multi(dsi_ctx); - mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x01); - - return 0; + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x4f, 0x01); } static int tm5p5_nt35596_prepare(struct drm_panel *panel) { struct tm5p5_nt35596 *ctx = to_tm5p5_nt35596(panel); - struct device *dev = &ctx->dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = {.dsi = ctx->dsi}; - ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - if (ret < 0) { - dev_err(dev, "Failed to enable regulators: %d\n", ret); - return ret; - } + dsi_ctx.accum_err = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); + if (dsi_ctx.accum_err) + return dsi_ctx.accum_err; tm5p5_nt35596_reset(ctx); - ret = tm5p5_nt35596_on(ctx); - if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); + tm5p5_nt35596_on(&dsi_ctx); + + if (dsi_ctx.accum_err) { gpiod_set_value_cansleep(ctx->reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - return ret; } - return 0; + return dsi_ctx.accum_err; } static int tm5p5_nt35596_unprepare(struct drm_panel *panel) { struct tm5p5_nt35596 *ctx = to_tm5p5_nt35596(panel); - struct device *dev = &ctx->dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = {.dsi = ctx->dsi}; - ret = tm5p5_nt35596_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + tm5p5_nt35596_off(&dsi_ctx); gpiod_set_value_cansleep(ctx->reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - return 0; + return dsi_ctx.accum_err; } static const struct drm_display_mode tm5p5_nt35596_mode = { diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c b/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c new file mode 100644 index 000000000000..e4a44cd26c4d --- /dev/null +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c @@ -0,0 +1,402 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include