mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-29 17:22:07 +00:00
drm-misc-next for $kernel-version:
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, -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCZn1DmQAKCRDj7w1vZxhR xYj3AP9ThM8q3HoCqXKerpEfnb5LYDB4NocLjn/Bamtm134oNQD+M4Gu2zLSVymV 74PwtPYuQGKWrmXdw0tD70/MtTAihQc= =fSI4 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
91fdc5e765
@ -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>;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -25,8 +25,8 @@ properties:
|
||||
|
||||
reg:
|
||||
enum:
|
||||
- 0x68
|
||||
- 0x0f
|
||||
- 0x68
|
||||
description: |
|
||||
i2c address of the bridge, 0x68 or 0x0f, depending on bootstrap pins
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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 <mwalle@kernel.org>
|
||||
|
||||
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 <dt-bindings/gpio/gpio.h>
|
||||
|
||||
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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 <mwalle@kernel.org>
|
||||
S: Maintained
|
||||
F: drivers/gpu/drm/panel/panel-ilitek-ili9806e.c
|
||||
|
||||
DRM DRIVER FOR JADARD JD9365DA-H3 MIPI-DSI LCD PANELS
|
||||
M: Jagan Teki <jagan@edgeble.ai>
|
||||
S: Maintained
|
||||
@ -7519,8 +7524,9 @@ F: include/uapi/drm/v3d_drm.h
|
||||
|
||||
DRM DRIVERS FOR VC4
|
||||
M: Maxime Ripard <mripard@kernel.org>
|
||||
M: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
R: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
|
||||
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/
|
||||
|
@ -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
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_panic.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -7,16 +7,19 @@
|
||||
*/
|
||||
|
||||
#include <linux/font.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/iosys-map.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/kmsg_dump.h>
|
||||
#include <linux/linux_logo.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_format_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 = {
|
||||
|
402
drivers/gpu/drm/panel/panel-ilitek-ili9806e.c
Normal file
402
drivers/gpu/drm/panel/panel-ilitek-ili9806e.c
Normal file
@ -0,0 +1,402 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
struct panel_desc {
|
||||
const struct drm_display_mode *display_mode;
|
||||
unsigned long mode_flags;
|
||||
enum mipi_dsi_pixel_format format;
|
||||
unsigned int lanes;
|
||||
void (*init_sequence)(struct mipi_dsi_multi_context *ctx);
|
||||
};
|
||||
|
||||
struct ili9806e_panel {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct regulator_bulk_data supplies[2];
|
||||
const struct panel_desc *desc;
|
||||
enum drm_panel_orientation orientation;
|
||||
};
|
||||
|
||||
static const char * const regulator_names[] = {
|
||||
"vdd",
|
||||
"vccio",
|
||||
};
|
||||
|
||||
static inline struct ili9806e_panel *to_ili9806e_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct ili9806e_panel, panel);
|
||||
}
|
||||
|
||||
static int ili9806e_power_on(struct ili9806e_panel *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
int ret;
|
||||
|
||||
gpiod_set_value(ctx->reset_gpio, 1);
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(&dsi->dev, "regulator bulk enable failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(10000, 20000);
|
||||
gpiod_set_value(ctx->reset_gpio, 0);
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ili9806e_power_off(struct ili9806e_panel *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
int ret;
|
||||
|
||||
gpiod_set_value(ctx->reset_gpio, 1);
|
||||
|
||||
ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
if (ret)
|
||||
dev_err(&dsi->dev, "regulator bulk disable failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ili9806e_on(struct ili9806e_panel *ili9806e)
|
||||
{
|
||||
struct mipi_dsi_multi_context ctx = { .dsi = ili9806e->dsi };
|
||||
|
||||
if (ili9806e->desc->init_sequence)
|
||||
ili9806e->desc->init_sequence(&ctx);
|
||||
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 120);
|
||||
mipi_dsi_dcs_set_display_on_multi(&ctx);
|
||||
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int ili9806e_off(struct ili9806e_panel *panel)
|
||||
{
|
||||
struct mipi_dsi_multi_context ctx = { .dsi = panel->dsi };
|
||||
|
||||
mipi_dsi_dcs_set_display_off_multi(&ctx);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 120);
|
||||
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int ili9806e_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct ili9806e_panel *ctx = to_ili9806e_panel(panel);
|
||||
int ret;
|
||||
|
||||
ret = ili9806e_power_on(ctx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ili9806e_on(ctx);
|
||||
if (ret < 0) {
|
||||
ili9806e_power_off(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ili9806e_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct ili9806e_panel *ctx = to_ili9806e_panel(panel);
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
int ret;
|
||||
|
||||
ili9806e_off(ctx);
|
||||
|
||||
ret = ili9806e_power_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "power off failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ili9806e_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct ili9806e_panel *ctx = to_ili9806e_panel(panel);
|
||||
const struct drm_display_mode *mode = ctx->desc->display_mode;
|
||||
|
||||
return drm_connector_helper_get_modes_fixed(connector, mode);
|
||||
}
|
||||
|
||||
static enum drm_panel_orientation ili9806e_get_orientation(struct drm_panel *panel)
|
||||
{
|
||||
struct ili9806e_panel *ctx = to_ili9806e_panel(panel);
|
||||
|
||||
return ctx->orientation;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs ili9806e_funcs = {
|
||||
.prepare = ili9806e_prepare,
|
||||
.unprepare = ili9806e_unprepare,
|
||||
.get_modes = ili9806e_get_modes,
|
||||
.get_orientation = ili9806e_get_orientation,
|
||||
};
|
||||
|
||||
static int ili9806e_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct device *dev = &dsi->dev;
|
||||
struct ili9806e_panel *ctx;
|
||||
int i, ret;
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->desc = device_get_match_data(dev);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++)
|
||||
ctx->supplies[i].supply = regulator_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
|
||||
ctx->supplies);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
|
||||
"Failed to get reset-gpios\n");
|
||||
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
ctx->dsi = dsi;
|
||||
|
||||
dsi->mode_flags = ctx->desc->mode_flags;
|
||||
dsi->format = ctx->desc->format;
|
||||
dsi->lanes = ctx->desc->lanes;
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &ili9806e_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to get orientation\n");
|
||||
|
||||
ret = drm_panel_of_backlight(&ctx->panel);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to get backlight\n");
|
||||
|
||||
ctx->panel.prepare_prev_first = true;
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
|
||||
drm_panel_remove(&ctx->panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ili9806e_dsi_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct ili9806e_panel *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
mipi_dsi_detach(dsi);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
}
|
||||
|
||||
static void com35h3p70ulc_init(struct mipi_dsi_multi_context *ctx)
|
||||
{
|
||||
/* Switch to page 1 */
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x01);
|
||||
/* Interface Settings */
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x18);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x01);
|
||||
/* Panel Settings */
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x03);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x60, 0x0d);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x61, 0x08);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x62, 0x08);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x63, 0x09);
|
||||
/* Power Control */
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x40, 0x30);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x41, 0x44);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x42, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x43, 0x89);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x44, 0x8e);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x45, 0xd9);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x46, 0x33);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x47, 0x33);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x50, 0x90);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x51, 0x90);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x56, 0x00);
|
||||
/* Gamma Settings */
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xa0, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xa1, 0x0c);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xa2, 0x13);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xa3, 0x0f);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xa4, 0x0a);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xa5, 0x0d);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xa6, 0x0c);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xa7, 0x0b);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xa8, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xa9, 0x06);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xaa, 0x15);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xab, 0x07);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xac, 0x12);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xad, 0x28);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xae, 0x20);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xaf, 0x14);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xc0, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xc1, 0x0c);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xc2, 0x13);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xc3, 0x0f);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xc4, 0x09);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xc5, 0x0d);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xc6, 0x0c);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xc7, 0x0b);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xc8, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xc9, 0x06);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xca, 0x14);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xcb, 0x07);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xcc, 0x0f);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xcd, 0x21);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xce, 0x17);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xcf, 0x0a);
|
||||
|
||||
/* Switch to page 7 */
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x07);
|
||||
/* Power Control */
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x06, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x18, 0x1d);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x32);
|
||||
|
||||
/* Switch to page 6 */
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x06);
|
||||
/* GIP settings */
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x00, 0x20);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x01, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x02, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x03, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x04, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x05, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x06, 0x88);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x07, 0x04);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x08, 0x03);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x09, 0x80);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x0a, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x0b, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x0c, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x0d, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x0e, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x0f, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x10, 0x55);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x11, 0x50);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x12, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x13, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x14, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x15, 0x43);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x16, 0x0b);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x17, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x18, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x19, 0x10);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x1a, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x1b, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x1c, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x1d, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x20, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x21, 0x23);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x22, 0x45);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x23, 0x67);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x24, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x25, 0x23);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x26, 0x45);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x27, 0x67);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x30, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x31, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x32, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x33, 0x88);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x34, 0xaa);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x35, 0xbb);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x36, 0x66);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x37, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x38, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x39, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x3a, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x3b, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x3c, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x3d, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x3e, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x3f, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x40, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x12);
|
||||
|
||||
/* Switch to page 0 */
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0xff, 0xff, 0x98, 0x06, 0x04, 0x00);
|
||||
/* Interface Pixel format */
|
||||
mipi_dsi_dcs_write_seq_multi(ctx, 0x3a, 0x60);
|
||||
};
|
||||
|
||||
static const struct drm_display_mode com35h3p70ulc_default_mode = {
|
||||
.clock = 22400,
|
||||
.hdisplay = 480,
|
||||
.hsync_start = 480 + 16,
|
||||
.hsync_end = 480 + 16 + 16,
|
||||
.htotal = 480 + 16 + 16 + 16,
|
||||
.vdisplay = 640,
|
||||
.vsync_start = 640 + 52,
|
||||
.vsync_end = 640 + 52 + 4,
|
||||
.vtotal = 640 + 52 + 4 + 16,
|
||||
.width_mm = 53,
|
||||
.height_mm = 71,
|
||||
};
|
||||
|
||||
static const struct panel_desc com35h3p70ulc_desc = {
|
||||
.init_sequence = com35h3p70ulc_init,
|
||||
.display_mode = &com35h3p70ulc_default_mode,
|
||||
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_LPM,
|
||||
.format = MIPI_DSI_FMT_RGB888,
|
||||
.lanes = 2,
|
||||
};
|
||||
|
||||
static const struct of_device_id ili9806e_of_match[] = {
|
||||
{ .compatible = "ortustech,com35h3p70ulc", .data = &com35h3p70ulc_desc },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ili9806e_of_match);
|
||||
|
||||
static struct mipi_dsi_driver ili9806e_dsi_driver = {
|
||||
.driver = {
|
||||
.name = "ili9806e-dsi",
|
||||
.of_match_table = ili9806e_of_match,
|
||||
},
|
||||
.probe = ili9806e_dsi_probe,
|
||||
.remove = ili9806e_dsi_remove,
|
||||
};
|
||||
module_mipi_dsi_driver(ili9806e_dsi_driver);
|
||||
|
||||
MODULE_AUTHOR("Gunnar Dibbern <gunnar.dibbern@lht.dlh.de>");
|
||||
MODULE_AUTHOR("Michael Walle <mwalle@kernel.org>");
|
||||
MODULE_DESCRIPTION("Ilitek ILI9806E Controller Driver");
|
||||
MODULE_LICENSE("GPL");
|
262
drivers/gpu/drm/panel/panel-lincolntech-lcd197.c
Normal file
262
drivers/gpu/drm/panel/panel-lincolntech-lcd197.c
Normal file
@ -0,0 +1,262 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2024 BayLibre, SAS
|
||||
* Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
struct lincoln_lcd197_panel {
|
||||
struct drm_panel panel;
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct regulator *supply;
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct gpio_desc *reset_gpio;
|
||||
};
|
||||
|
||||
static inline
|
||||
struct lincoln_lcd197_panel *to_lincoln_lcd197_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct lincoln_lcd197_panel, panel);
|
||||
}
|
||||
|
||||
static int lincoln_lcd197_panel_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel);
|
||||
struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi };
|
||||
int err;
|
||||
|
||||
gpiod_set_value_cansleep(lcd->enable_gpio, 0);
|
||||
err = regulator_enable(lcd->supply);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
gpiod_set_value_cansleep(lcd->enable_gpio, 1);
|
||||
usleep_range(1000, 2000);
|
||||
gpiod_set_value_cansleep(lcd->reset_gpio, 1);
|
||||
usleep_range(5000, 6000);
|
||||
gpiod_set_value_cansleep(lcd->reset_gpio, 0);
|
||||
msleep(50);
|
||||
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0xff, 0x83, 0x99);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xd2, 0x55);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0x02, 0x04, 0x70, 0x90, 0x01,
|
||||
0x32, 0x33, 0x11, 0x11, 0x4d, 0x57, 0x56, 0x73,
|
||||
0x02, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xb2, 0x00, 0x80, 0x80, 0xae, 0x0a,
|
||||
0x0e, 0x75, 0x11, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xb4, 0x00, 0xff, 0x04, 0xa4, 0x02,
|
||||
0xa0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00,
|
||||
0x24, 0x02, 0x04, 0x0a, 0x21, 0x03, 0x00, 0x00,
|
||||
0x08, 0xa6, 0x88, 0x04, 0xa4, 0x02, 0xa0, 0x00,
|
||||
0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x24, 0x02,
|
||||
0x04, 0x0a, 0x00, 0x00, 0x08, 0xa6, 0x00, 0x08,
|
||||
0x11);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x18, 0x18, 0x32, 0x10, 0x09, 0x00, 0x09,
|
||||
0x32, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x11, 0x00, 0x02, 0x02, 0x03, 0x00,
|
||||
0x00, 0x00, 0x0a, 0x40);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xd5, 0x18, 0x18, 0x18, 0x18, 0x21,
|
||||
0x20, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x18,
|
||||
0x18, 0x18, 0x18, 0x03, 0x02, 0x01, 0x00, 0x2f,
|
||||
0x2f, 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x18, 0x18, 0x18, 0x18, 0x20,
|
||||
0x21, 0x19, 0x19, 0x18, 0x18, 0x19, 0x19, 0x18,
|
||||
0x18, 0x18, 0x18, 0x00, 0x01, 0x02, 0x03, 0x2f,
|
||||
0x2f, 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0a, 0xbe, 0xfa, 0xa0, 0x0a,
|
||||
0xbe, 0xfa, 0xa0);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0f, 0xff, 0xff, 0xe0, 0x0f,
|
||||
0xff, 0xff, 0xe0);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xd8, 0x0f, 0xff, 0xff, 0xe0, 0x0f,
|
||||
0xff, 0xff, 0xe0);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x01, 0x11, 0x1c, 0x17, 0x39,
|
||||
0x43, 0x54, 0x51, 0x5a, 0x64, 0x6c, 0x74, 0x7a,
|
||||
0x83, 0x8d, 0x92, 0x99, 0xa4, 0xa9, 0xb4, 0xaa,
|
||||
0xba, 0xbe, 0x63, 0x5e, 0x69, 0x73, 0x01, 0x11,
|
||||
0x1c, 0x17, 0x39, 0x43, 0x54, 0x51, 0x5a, 0x64,
|
||||
0x6c, 0x74, 0x7a, 0x83, 0x8d, 0x92, 0x99, 0xa4,
|
||||
0xa7, 0xb2, 0xa9, 0xba, 0xbe, 0x63, 0x5e, 0x69,
|
||||
0x73);
|
||||
mipi_dsi_usleep_range(&ctx, 200, 300);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xb6, 0x92, 0x92);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xcc, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xbf, 0x40, 0x41, 0x50, 0x49);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xff, 0xf9);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x25, 0x5a);
|
||||
mipi_dsi_dcs_write_seq_multi(&ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x02);
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 120);
|
||||
|
||||
if (ctx.accum_err) {
|
||||
gpiod_set_value_cansleep(lcd->enable_gpio, 0);
|
||||
gpiod_set_value_cansleep(lcd->reset_gpio, 1);
|
||||
regulator_disable(lcd->supply);
|
||||
}
|
||||
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int lincoln_lcd197_panel_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel);
|
||||
struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi };
|
||||
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
|
||||
mipi_dsi_usleep_range(&ctx, 5000, 6000);
|
||||
gpiod_set_value_cansleep(lcd->enable_gpio, 0);
|
||||
gpiod_set_value_cansleep(lcd->reset_gpio, 1);
|
||||
regulator_disable(lcd->supply);
|
||||
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int lincoln_lcd197_panel_enable(struct drm_panel *panel)
|
||||
{
|
||||
struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel);
|
||||
struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi };
|
||||
|
||||
mipi_dsi_dcs_set_display_on_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 20);
|
||||
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static int lincoln_lcd197_panel_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct lincoln_lcd197_panel *lcd = to_lincoln_lcd197_panel(panel);
|
||||
struct mipi_dsi_multi_context ctx = { .dsi = lcd->dsi };
|
||||
|
||||
mipi_dsi_dcs_set_display_off_multi(&ctx);
|
||||
mipi_dsi_msleep(&ctx, 50);
|
||||
|
||||
return ctx.accum_err;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode lcd197_mode = {
|
||||
.clock = 154002,
|
||||
.hdisplay = 1080,
|
||||
.hsync_start = 1080 + 20,
|
||||
.hsync_end = 1080 + 20 + 6,
|
||||
.htotal = 1080 + 204,
|
||||
.vdisplay = 1920,
|
||||
.vsync_start = 1920 + 4,
|
||||
.vsync_end = 1920 + 4 + 4,
|
||||
.vtotal = 1920 + 79,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
.width_mm = 79,
|
||||
.height_mm = 125,
|
||||
.type = DRM_MODE_TYPE_DRIVER,
|
||||
};
|
||||
|
||||
static int lincoln_lcd197_panel_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
return drm_connector_helper_get_modes_fixed(connector, &lcd197_mode);
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs lincoln_lcd197_panel_funcs = {
|
||||
.prepare = lincoln_lcd197_panel_prepare,
|
||||
.unprepare = lincoln_lcd197_panel_unprepare,
|
||||
.enable = lincoln_lcd197_panel_enable,
|
||||
.disable = lincoln_lcd197_panel_disable,
|
||||
.get_modes = lincoln_lcd197_panel_get_modes,
|
||||
};
|
||||
|
||||
static int lincoln_lcd197_panel_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct lincoln_lcd197_panel *lcd;
|
||||
struct device *dev = &dsi->dev;
|
||||
int err;
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = (MIPI_DSI_MODE_VIDEO |
|
||||
MIPI_DSI_MODE_VIDEO_BURST);
|
||||
|
||||
lcd = devm_kzalloc(&dsi->dev, sizeof(*lcd), GFP_KERNEL);
|
||||
if (!lcd)
|
||||
return -ENOMEM;
|
||||
|
||||
mipi_dsi_set_drvdata(dsi, lcd);
|
||||
lcd->dsi = dsi;
|
||||
|
||||
lcd->supply = devm_regulator_get(dev, "power");
|
||||
if (IS_ERR(lcd->supply))
|
||||
return dev_err_probe(dev, PTR_ERR(lcd->supply),
|
||||
"failed to get power supply");
|
||||
|
||||
lcd->enable_gpio = devm_gpiod_get(dev, "enable",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(lcd->enable_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(lcd->enable_gpio),
|
||||
"failed to get enable gpio");
|
||||
|
||||
lcd->reset_gpio = devm_gpiod_get(dev, "reset",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(lcd->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(lcd->reset_gpio),
|
||||
"failed to get reset gpio");
|
||||
|
||||
drm_panel_init(&lcd->panel, dev,
|
||||
&lincoln_lcd197_panel_funcs, DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
err = drm_panel_of_backlight(&lcd->panel);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
drm_panel_add(&lcd->panel);
|
||||
err = mipi_dsi_attach(dsi);
|
||||
if (err)
|
||||
drm_panel_remove(&lcd->panel);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void lincoln_lcd197_panel_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct lincoln_lcd197_panel *lcd = mipi_dsi_get_drvdata(dsi);
|
||||
int err;
|
||||
|
||||
err = mipi_dsi_detach(dsi);
|
||||
if (err < 0)
|
||||
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
|
||||
|
||||
drm_panel_remove(&lcd->panel);
|
||||
}
|
||||
|
||||
static const struct of_device_id lincoln_lcd197_of_match[] = {
|
||||
{ .compatible = "lincolntech,lcd197", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lincoln_lcd197_of_match);
|
||||
|
||||
static struct mipi_dsi_driver lincoln_lcd197_panel_driver = {
|
||||
.driver = {
|
||||
.name = "panel-lincolntech-lcd197",
|
||||
.of_match_table = lincoln_lcd197_of_match,
|
||||
},
|
||||
.probe = lincoln_lcd197_panel_probe,
|
||||
.remove = lincoln_lcd197_panel_remove,
|
||||
};
|
||||
module_mipi_dsi_driver(lincoln_lcd197_panel_driver);
|
||||
|
||||
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
|
||||
MODULE_DESCRIPTION("Lincoln Technologies LCD197 panel driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -40,176 +40,136 @@ static void rm692e5_reset(struct rm692e5_panel *ctx)
|
||||
usleep_range(10000, 11000);
|
||||
}
|
||||
|
||||
static int rm692e5_on(struct rm692e5_panel *ctx)
|
||||
static void rm692e5_on(struct mipi_dsi_multi_context *dsi_ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
dsi_ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x41);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd6, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x16);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x8a, 0x87);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x71);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x82, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc6, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc7, 0x2c);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc8, 0x64);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc9, 0x3c);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xca, 0x80);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xcb, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xcc, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x38);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0x13);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xf4);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x00, 0xff);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x01, 0xff);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x02, 0xcf);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x03, 0xbc);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x04, 0xb9);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x05, 0x99);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x06, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x07, 0x0a);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x08, 0xe0);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x09, 0x4c);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0a, 0xeb);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0b, 0xe8);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0c, 0x32);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0d, 0x07);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xf4);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0d, 0xc0);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0e, 0xff);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x0f, 0xff);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x10, 0x33);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x11, 0x6f);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x12, 0x6e);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x13, 0xa6);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x14, 0x80);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x15, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x16, 0x38);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x17, 0xd3);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0x3a);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x19, 0xba);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1a, 0xcc);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1b, 0x01);
|
||||
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfe, 0x41);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd6, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfe, 0x16);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x8a, 0x87);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfe, 0x71);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x82, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc6, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc7, 0x2c);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc8, 0x64);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc9, 0x3c);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xca, 0x80);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcb, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcc, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfe, 0x38);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x18, 0x13);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfe, 0xf4);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x00, 0xff);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x01, 0xff);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x02, 0xcf);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x03, 0xbc);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x04, 0xb9);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x05, 0x99);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x06, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x07, 0x0a);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x08, 0xe0);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x09, 0x4c);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0a, 0xeb);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0b, 0xe8);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0c, 0x32);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0d, 0x07);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfe, 0xf4);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0d, 0xc0);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0e, 0xff);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x0f, 0xff);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x10, 0x33);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x11, 0x6f);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x12, 0x6e);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x13, 0xa6);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x14, 0x80);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x15, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x16, 0x38);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x17, 0xd3);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x18, 0x3a);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x19, 0xba);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x1a, 0xcc);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x1b, 0x01);
|
||||
mipi_dsi_dcs_nop_multi(dsi_ctx);
|
||||
|
||||
ret = mipi_dsi_dcs_nop(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to nop: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(32);
|
||||
mipi_dsi_msleep(dsi_ctx, 32);
|
||||
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfe, 0x38);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x18, 0x13);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfe, 0xd1);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd3, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd0, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd2, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd4, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb4, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfe, 0xf9);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x00, 0xaf);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x1d, 0x37);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x44, 0x0a, 0x7b);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfe, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfa, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc2, 0x08);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x35, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x51, 0x05, 0x42);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x38);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x18, 0x13);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xd1);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd3, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd0, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd2, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xd4, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xb4, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0xf9);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x00, 0xaf);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x1d, 0x37);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x44, 0x0a, 0x7b);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfe, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xfa, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0xc2, 0x08);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x35, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x51, 0x05, 0x42);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(100);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
|
||||
mipi_dsi_msleep(dsi_ctx, 100);
|
||||
mipi_dsi_dcs_set_display_on_multi(dsi_ctx);
|
||||
}
|
||||
|
||||
static int rm692e5_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct rm692e5_panel *ctx = to_rm692e5_panel(panel);
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
mipi_dsi_generic_write_seq(dsi, 0xfe, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xfe, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(100);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
|
||||
|
||||
return 0;
|
||||
mipi_dsi_msleep(&dsi_ctx, 100);
|
||||
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int rm692e5_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct rm692e5_panel *ctx = to_rm692e5_panel(panel);
|
||||
struct drm_dsc_picture_parameter_set pps;
|
||||
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;
|
||||
|
||||
rm692e5_reset(ctx);
|
||||
|
||||
ret = rm692e5_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
return ret;
|
||||
}
|
||||
rm692e5_on(&dsi_ctx);
|
||||
|
||||
drm_dsc_pps_payload_pack(&pps, &ctx->dsc);
|
||||
|
||||
ret = mipi_dsi_picture_parameter_set(ctx->dsi, &pps);
|
||||
if (ret < 0) {
|
||||
dev_err(panel->dev, "failed to transmit PPS: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps);
|
||||
mipi_dsi_compression_mode_ext_multi(&dsi_ctx, true, MIPI_DSI_COMPRESSION_DSC, 0);
|
||||
mipi_dsi_msleep(&dsi_ctx, 28);
|
||||
|
||||
ret = mipi_dsi_compression_mode(ctx->dsi, true);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to enable compression mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
msleep(28);
|
||||
|
||||
mipi_dsi_generic_write_seq(ctx->dsi, 0xfe, 0x40);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xfe, 0x40);
|
||||
|
||||
/* 0x05 -> 90Hz, 0x00 -> 60Hz */
|
||||
mipi_dsi_generic_write_seq(ctx->dsi, 0xbd, 0x05);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x05);
|
||||
|
||||
mipi_dsi_generic_write_seq(ctx->dsi, 0xfe, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xfe, 0x00);
|
||||
|
||||
return 0;
|
||||
if (dsi_ctx.accum_err) {
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
}
|
||||
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int rm692e5_unprepare(struct drm_panel *panel)
|
||||
|
@ -69,7 +69,7 @@ struct st7703_panel_desc {
|
||||
unsigned int lanes;
|
||||
unsigned long mode_flags;
|
||||
enum mipi_dsi_pixel_format format;
|
||||
int (*init_sequence)(struct st7703 *ctx);
|
||||
void (*init_sequence)(struct mipi_dsi_multi_context *dsi_ctx);
|
||||
};
|
||||
|
||||
static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
|
||||
@ -77,62 +77,58 @@ static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
|
||||
return container_of(panel, struct st7703, panel);
|
||||
}
|
||||
|
||||
static int jh057n_init_sequence(struct st7703 *ctx)
|
||||
static void jh057n_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
|
||||
/*
|
||||
* Init sequence was supplied by the panel vendor. Most of the commands
|
||||
* resemble the ST7703 but the number of parameters often don't match
|
||||
* so it's likely a clone.
|
||||
*/
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC,
|
||||
0xF1, 0x12, 0x83);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF,
|
||||
0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR,
|
||||
0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
|
||||
0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ,
|
||||
0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08);
|
||||
msleep(20);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC,
|
||||
0xF1, 0x12, 0x83);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF,
|
||||
0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR,
|
||||
0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
|
||||
0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x4E);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0B);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ,
|
||||
0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x08, 0x08);
|
||||
mipi_dsi_msleep(dsi_ctx, 20);
|
||||
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1,
|
||||
0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
|
||||
0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
|
||||
0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
|
||||
0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2,
|
||||
0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
|
||||
0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
|
||||
0xA5, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA,
|
||||
0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
|
||||
0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
|
||||
0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
|
||||
0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
|
||||
0x11, 0x18);
|
||||
msleep(20);
|
||||
|
||||
return 0;
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1,
|
||||
0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
|
||||
0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
|
||||
0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
|
||||
0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2,
|
||||
0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
|
||||
0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
|
||||
0xA5, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA,
|
||||
0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
|
||||
0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
|
||||
0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
|
||||
0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
|
||||
0x11, 0x18);
|
||||
mipi_dsi_msleep(dsi_ctx, 20);
|
||||
}
|
||||
|
||||
static const struct drm_display_mode jh057n00900_mode = {
|
||||
@ -159,163 +155,159 @@ static const struct st7703_panel_desc jh057n00900_panel_desc = {
|
||||
.init_sequence = jh057n_init_sequence,
|
||||
};
|
||||
|
||||
static int xbd599_init_sequence(struct st7703 *ctx)
|
||||
static void xbd599_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
|
||||
/*
|
||||
* Init sequence was supplied by the panel vendor.
|
||||
*/
|
||||
|
||||
/* Magic sequence to unlock user commands below. */
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI,
|
||||
0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */
|
||||
0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */
|
||||
0x05, /* IHSRX = x6 (Low High Speed driving ability) */
|
||||
0xF9, /* TX_CLK_SEL = fDSICLK/16 */
|
||||
0x0E, /* HFP_OSC (min. HFP number in DSI mode) */
|
||||
0x0E, /* HBP_OSC (min. HBP number in DSI mode) */
|
||||
/* The rest is undocumented in ST7703 datasheet */
|
||||
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
|
||||
0x4F, 0x11, 0x00, 0x00, 0x37);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI,
|
||||
0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */
|
||||
0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */
|
||||
0x05, /* IHSRX = x6 (Low High Speed driving ability) */
|
||||
0xF9, /* TX_CLK_SEL = fDSICLK/16 */
|
||||
0x0E, /* HFP_OSC (min. HFP number in DSI mode) */
|
||||
0x0E, /* HBP_OSC (min. HBP number in DSI mode) */
|
||||
/* The rest is undocumented in ST7703 datasheet */
|
||||
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
|
||||
0x4F, 0x11, 0x00, 0x00, 0x37);
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT,
|
||||
0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */
|
||||
0x22, /* DT = 15ms XDK_ECP = x2 */
|
||||
0x20, /* PFM_DC_DIV = /1 */
|
||||
0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT,
|
||||
0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */
|
||||
0x22, /* DT = 15ms XDK_ECP = x2 */
|
||||
0x20, /* PFM_DC_DIV = /1 */
|
||||
0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */);
|
||||
|
||||
/* RGB I/F porch timing */
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF,
|
||||
0x10, /* VBP_RGB_GEN */
|
||||
0x10, /* VFP_RGB_GEN */
|
||||
0x05, /* DE_BP_RGB_GEN */
|
||||
0x05, /* DE_FP_RGB_GEN */
|
||||
/* The rest is undocumented in ST7703 datasheet */
|
||||
0x03, 0xFF,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF,
|
||||
0x10, /* VBP_RGB_GEN */
|
||||
0x10, /* VFP_RGB_GEN */
|
||||
0x05, /* DE_BP_RGB_GEN */
|
||||
0x05, /* DE_FP_RGB_GEN */
|
||||
/* The rest is undocumented in ST7703 datasheet */
|
||||
0x03, 0xFF,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00);
|
||||
|
||||
/* Source driving settings. */
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR,
|
||||
0x73, /* N_POPON */
|
||||
0x73, /* N_NOPON */
|
||||
0x50, /* I_POPON */
|
||||
0x50, /* I_NOPON */
|
||||
0x00, /* SCR[31,24] */
|
||||
0xC0, /* SCR[23,16] */
|
||||
0x08, /* SCR[15,8] */
|
||||
0x70, /* SCR[7,0] */
|
||||
0x00 /* Undocumented */);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR,
|
||||
0x73, /* N_POPON */
|
||||
0x73, /* N_NOPON */
|
||||
0x50, /* I_POPON */
|
||||
0x50, /* I_NOPON */
|
||||
0x00, /* SCR[31,24] */
|
||||
0xC0, /* SCR[23,16] */
|
||||
0x08, /* SCR[15,8] */
|
||||
0x70, /* SCR[7,0] */
|
||||
0x00 /* Undocumented */);
|
||||
|
||||
/* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x4E);
|
||||
|
||||
/*
|
||||
* SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan)
|
||||
* REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR)
|
||||
*/
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0B);
|
||||
|
||||
/* Zig-Zag Type C column inversion. */
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
|
||||
|
||||
/* Set display resolution. */
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP,
|
||||
0xF0, /* NL = 240 */
|
||||
0x12, /* RES_V_LSB = 0, BLK_CON = VSSD,
|
||||
* RESO_SEL = 720RGB
|
||||
*/
|
||||
0xF0 /* WHITE_GND_EN = 1 (GND),
|
||||
* WHITE_FRAME_SEL = 7 frames,
|
||||
* ISC = 0 frames
|
||||
*/);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP,
|
||||
0xF0, /* NL = 240 */
|
||||
0x12, /* RES_V_LSB = 0, BLK_CON = VSSD,
|
||||
* RESO_SEL = 720RGB
|
||||
*/
|
||||
0xF0 /* WHITE_GND_EN = 1 (GND),
|
||||
* WHITE_FRAME_SEL = 7 frames,
|
||||
* ISC = 0 frames
|
||||
*/);
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ,
|
||||
0x00, /* PNOEQ */
|
||||
0x00, /* NNOEQ */
|
||||
0x0B, /* PEQGND */
|
||||
0x0B, /* NEQGND */
|
||||
0x10, /* PEQVCI */
|
||||
0x10, /* NEQVCI */
|
||||
0x00, /* PEQVCI1 */
|
||||
0x00, /* NEQVCI1 */
|
||||
0x00, /* reserved */
|
||||
0x00, /* reserved */
|
||||
0xFF, /* reserved */
|
||||
0x00, /* reserved */
|
||||
0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */
|
||||
0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in)
|
||||
* VEDIO_NO_CHECK_EN = 0
|
||||
* ESD_WHITE_GND_EN = 0
|
||||
* ESD_DET_TIME_SEL = 0 frames
|
||||
*/);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ,
|
||||
0x00, /* PNOEQ */
|
||||
0x00, /* NNOEQ */
|
||||
0x0B, /* PEQGND */
|
||||
0x0B, /* NEQGND */
|
||||
0x10, /* PEQVCI */
|
||||
0x10, /* NEQVCI */
|
||||
0x00, /* PEQVCI1 */
|
||||
0x00, /* NEQVCI1 */
|
||||
0x00, /* reserved */
|
||||
0x00, /* reserved */
|
||||
0xFF, /* reserved */
|
||||
0x00, /* reserved */
|
||||
0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */
|
||||
0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in)
|
||||
* VEDIO_NO_CHECK_EN = 0
|
||||
* ESD_WHITE_GND_EN = 0
|
||||
* ESD_DET_TIME_SEL = 0 frames
|
||||
*/);
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x01, 0x00, 0xFF, 0xFF, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x01, 0x00, 0xFF, 0xFF, 0x00);
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,
|
||||
0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
|
||||
0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */
|
||||
0x32, /* VRP */
|
||||
0x32, /* VRN */
|
||||
0x77, /* reserved */
|
||||
0xF1, /* APS = 1 (small),
|
||||
* VGL_DET_EN = 1, VGH_DET_EN = 1,
|
||||
* VGL_TURBO = 1, VGH_TURBO = 1
|
||||
*/
|
||||
0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */
|
||||
0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */
|
||||
0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */
|
||||
0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */
|
||||
0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */
|
||||
0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER,
|
||||
0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
|
||||
0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */
|
||||
0x32, /* VRP */
|
||||
0x32, /* VRN */
|
||||
0x77, /* reserved */
|
||||
0xF1, /* APS = 1 (small),
|
||||
* VGL_DET_EN = 1, VGH_DET_EN = 1,
|
||||
* VGL_TURBO = 1, VGH_TURBO = 1
|
||||
*/
|
||||
0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */
|
||||
0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */
|
||||
0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */
|
||||
0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */
|
||||
0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */
|
||||
0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);
|
||||
|
||||
/* Reference voltage. */
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
|
||||
0x07, /* VREF_SEL = 4.2V */
|
||||
0x07 /* NVREF_SEL = 4.2V */);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP,
|
||||
0x07, /* VREF_SEL = 4.2V */
|
||||
0x07 /* NVREF_SEL = 4.2V */);
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
|
||||
0x2C, /* VCOMDC_F = -0.67V */
|
||||
0x2C /* VCOMDC_B = -0.67V */);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM,
|
||||
0x2C, /* VCOMDC_F = -0.67V */
|
||||
0x2C /* VCOMDC_B = -0.67V */);
|
||||
|
||||
/* Undocumented command. */
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
|
||||
/* This command is to set forward GIP timing. */
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1,
|
||||
0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
|
||||
0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
|
||||
0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
|
||||
0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1,
|
||||
0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
|
||||
0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
|
||||
0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
|
||||
0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
|
||||
/* This command is to set backward GIP timing. */
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2,
|
||||
0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
|
||||
0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
|
||||
0xA5, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2,
|
||||
0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
|
||||
0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
|
||||
0xA5, 0x00, 0x00, 0x00, 0x00);
|
||||
|
||||
/* Adjust the gamma characteristics of the panel. */
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA,
|
||||
0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
|
||||
0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
|
||||
0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
|
||||
0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
|
||||
0x12, 0x18);
|
||||
|
||||
return 0;
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA,
|
||||
0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
|
||||
0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
|
||||
0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
|
||||
0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
|
||||
0x12, 0x18);
|
||||
}
|
||||
|
||||
static const struct drm_display_mode xbd599_mode = {
|
||||
@ -341,72 +333,68 @@ static const struct st7703_panel_desc xbd599_desc = {
|
||||
.init_sequence = xbd599_init_sequence,
|
||||
};
|
||||
|
||||
static int rg353v2_init_sequence(struct st7703 *ctx)
|
||||
static void rg353v2_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
|
||||
/*
|
||||
* Init sequence was supplied by the panel vendor.
|
||||
*/
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00,
|
||||
0xda, 0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x00, 0x13, 0x70);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
|
||||
0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x0a, 0x0a);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x92, 0x92);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22,
|
||||
0xf0, 0x63);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05,
|
||||
0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a,
|
||||
0x00, 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x47);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
|
||||
0x00, 0x00, 0x12, 0x50, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x53, 0xc0, 0x32,
|
||||
0x32, 0x77, 0xe1, 0xdd, 0xdd, 0x77, 0x77, 0x33,
|
||||
0x33);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff,
|
||||
0x00, 0xff);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00,
|
||||
0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e,
|
||||
0x02);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0d,
|
||||
0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 0x0d,
|
||||
0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a, 0x00, 0x07,
|
||||
0x0d, 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c,
|
||||
0x0d, 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
|
||||
0xc0, 0x10);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x02, 0x00,
|
||||
0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x80,
|
||||
0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
|
||||
0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,
|
||||
0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,
|
||||
0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x81, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x80, 0x88, 0xba, 0x06, 0x42,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
|
||||
0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01);
|
||||
|
||||
return 0;
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00,
|
||||
0xda, 0x80);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x00, 0x13, 0x70);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
|
||||
0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x0a, 0x0a);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x92, 0x92);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22,
|
||||
0xf0, 0x63);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05,
|
||||
0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a,
|
||||
0x00, 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x47);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
|
||||
0x00, 0x00, 0x12, 0x50, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x53, 0xc0, 0x32,
|
||||
0x32, 0x77, 0xe1, 0xdd, 0xdd, 0x77, 0x77, 0x33,
|
||||
0x33);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff,
|
||||
0x00, 0xff);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00,
|
||||
0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e,
|
||||
0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0d,
|
||||
0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 0x0d,
|
||||
0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a, 0x00, 0x07,
|
||||
0x0d, 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c,
|
||||
0x0d, 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
|
||||
0xc0, 0x10);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x02, 0x00,
|
||||
0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x80,
|
||||
0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
|
||||
0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,
|
||||
0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,
|
||||
0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x81, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x80, 0x88, 0xba, 0x06, 0x42,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
|
||||
0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01);
|
||||
}
|
||||
|
||||
static const struct drm_display_mode rg353v2_mode = {
|
||||
@ -433,68 +421,64 @@ static const struct st7703_panel_desc rg353v2_desc = {
|
||||
.init_sequence = rg353v2_init_sequence,
|
||||
};
|
||||
|
||||
static int rgb30panel_init_sequence(struct st7703 *ctx)
|
||||
static void rgb30panel_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
|
||||
/* Init sequence extracted from Powkiddy RGB30 BSP kernel. */
|
||||
|
||||
/*
|
||||
* For some reason this specific panel must be taken out of sleep
|
||||
* before the full init sequence, or else it will not display.
|
||||
*/
|
||||
mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
msleep(250);
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
|
||||
mipi_dsi_msleep(dsi_ctx, 250);
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9,
|
||||
0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00,
|
||||
0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0,
|
||||
0x63);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
|
||||
0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
|
||||
0x00, 0x00, 0x12, 0x70, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x46);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x3c, 0x12, 0x30);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
|
||||
0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
|
||||
0xc0, 0x10);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x36, 0x00, 0x32,
|
||||
0x32, 0x77, 0xf1, 0xcc, 0xcc, 0x77, 0x77, 0x33,
|
||||
0x33);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x0a, 0x0a);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x88, 0x88);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x0a, 0x10,
|
||||
0x0f, 0xa1, 0x80, 0x12, 0x31, 0x23, 0x47, 0x86,
|
||||
0xa1, 0x80, 0x47, 0x08, 0x00, 0x00, 0x0d, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
|
||||
0x48, 0x02, 0x8b, 0xaf, 0x46, 0x02, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x48, 0x13, 0x8b, 0xaf, 0x57,
|
||||
0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x96, 0x12, 0x01, 0x01,
|
||||
0x01, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4f, 0x31, 0x8b, 0xa8, 0x31, 0x75, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x4f, 0x20, 0x8b, 0xa8, 0x20,
|
||||
0x64, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
|
||||
0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x40, 0xa1, 0x80, 0x00, 0x00, 0x00,
|
||||
0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x0a, 0x0f,
|
||||
0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d, 0x10,
|
||||
0x13, 0x15, 0x14, 0x15, 0x10, 0x17, 0x00, 0x0a,
|
||||
0x0f, 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d,
|
||||
0x10, 0x13, 0x15, 0x14, 0x15, 0x10, 0x17);
|
||||
|
||||
return 0;
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9,
|
||||
0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00,
|
||||
0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0,
|
||||
0x63);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
|
||||
0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
|
||||
0x00, 0x00, 0x12, 0x70, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x46);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x3c, 0x12, 0x30);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
|
||||
0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
|
||||
0xc0, 0x10);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x36, 0x00, 0x32,
|
||||
0x32, 0x77, 0xf1, 0xcc, 0xcc, 0x77, 0x77, 0x33,
|
||||
0x33);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x0a, 0x0a);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x88, 0x88);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x0a, 0x10,
|
||||
0x0f, 0xa1, 0x80, 0x12, 0x31, 0x23, 0x47, 0x86,
|
||||
0xa1, 0x80, 0x47, 0x08, 0x00, 0x00, 0x0d, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
|
||||
0x48, 0x02, 0x8b, 0xaf, 0x46, 0x02, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x48, 0x13, 0x8b, 0xaf, 0x57,
|
||||
0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x96, 0x12, 0x01, 0x01,
|
||||
0x01, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4f, 0x31, 0x8b, 0xa8, 0x31, 0x75, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x4f, 0x20, 0x8b, 0xa8, 0x20,
|
||||
0x64, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
|
||||
0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x40, 0xa1, 0x80, 0x00, 0x00, 0x00,
|
||||
0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x0a, 0x0f,
|
||||
0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d, 0x10,
|
||||
0x13, 0x15, 0x14, 0x15, 0x10, 0x17, 0x00, 0x0a,
|
||||
0x0f, 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d,
|
||||
0x10, 0x13, 0x15, 0x14, 0x15, 0x10, 0x17);
|
||||
}
|
||||
|
||||
static const struct drm_display_mode rgb30panel_mode = {
|
||||
@ -521,70 +505,66 @@ static const struct st7703_panel_desc rgb30panel_desc = {
|
||||
.init_sequence = rgb30panel_init_sequence,
|
||||
};
|
||||
|
||||
static int rgb10max3_panel_init_sequence(struct st7703 *ctx)
|
||||
static void rgb10max3_panel_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
|
||||
/* Init sequence extracted from Powkiddy RGB10MAX3 BSP kernel. */
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 0xda,
|
||||
0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0xc8, 0x02, 0x30);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
|
||||
0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x04, 0x04);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x78, 0x78);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0,
|
||||
0x63);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9,
|
||||
0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00,
|
||||
0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x47);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
|
||||
0x00, 0x00, 0x12, 0x70, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x25, 0x00, 0x32,
|
||||
0x32, 0x77, 0xe1, 0xff, 0xff, 0xcc, 0xcc, 0x77,
|
||||
0x77);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff,
|
||||
0x00, 0xff);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00,
|
||||
0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e,
|
||||
0x02);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x04, 0x07,
|
||||
0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b, 0x0e,
|
||||
0x12, 0x14, 0x12, 0x13, 0x0f, 0x17, 0x00, 0x04,
|
||||
0x07, 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b,
|
||||
0x0e, 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x03, 0x03, 0x03, 0x03,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80,
|
||||
0xc0, 0x10);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x08, 0x00,
|
||||
0x00, 0x41, 0xf8, 0x12, 0x31, 0x23, 0x37, 0x86,
|
||||
0x11, 0xc8, 0x37, 0x2a, 0x00, 0x00, 0x0c, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x88, 0x20, 0x46, 0x02, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0xff, 0x88, 0x31, 0x57, 0x13, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x00, 0x1a, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x8f, 0x13, 0x31, 0x75, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0xf8, 0x8f, 0x02, 0x20, 0x64, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0xf8, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01);
|
||||
|
||||
return 0;
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 0xda,
|
||||
0x80);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0xc8, 0x02, 0x30);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
|
||||
0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x04, 0x04);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x78, 0x78);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0,
|
||||
0x63);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9,
|
||||
0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00,
|
||||
0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x47);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
|
||||
0x00, 0x00, 0x12, 0x70, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x25, 0x00, 0x32,
|
||||
0x32, 0x77, 0xe1, 0xff, 0xff, 0xcc, 0xcc, 0x77,
|
||||
0x77);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff,
|
||||
0x00, 0xff);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00,
|
||||
0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e,
|
||||
0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x04, 0x07,
|
||||
0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b, 0x0e,
|
||||
0x12, 0x14, 0x12, 0x13, 0x0f, 0x17, 0x00, 0x04,
|
||||
0x07, 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b,
|
||||
0x0e, 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x03, 0x03, 0x03, 0x03,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80,
|
||||
0xc0, 0x10);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x08, 0x00,
|
||||
0x00, 0x41, 0xf8, 0x12, 0x31, 0x23, 0x37, 0x86,
|
||||
0x11, 0xc8, 0x37, 0x2a, 0x00, 0x00, 0x0c, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x88, 0x20, 0x46, 0x02, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0xff, 0x88, 0x31, 0x57, 0x13, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x00, 0x1a, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x8f, 0x13, 0x31, 0x75, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0xf8, 0x8f, 0x02, 0x20, 0x64, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0xf8, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01);
|
||||
}
|
||||
|
||||
static const struct drm_display_mode rgb10max3_panel_mode = {
|
||||
@ -611,66 +591,62 @@ static const struct st7703_panel_desc rgb10max3_panel_desc = {
|
||||
.init_sequence = rgb10max3_panel_init_sequence,
|
||||
};
|
||||
|
||||
static int gameforcechi_init_sequence(struct st7703 *ctx)
|
||||
static void gameforcechi_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
|
||||
/*
|
||||
* Init sequence was supplied by the panel vendor. Panel will not
|
||||
* respond to commands until it is brought out of sleep mode first.
|
||||
*/
|
||||
|
||||
mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
msleep(250);
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
|
||||
mipi_dsi_msleep(dsi_ctx, 250);
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x31, 0x81, 0x05, 0xf9,
|
||||
0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00,
|
||||
0x00, 0x02, 0x4f, 0xd1, 0x00, 0x00, 0x37);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x0c, 0x10, 0x0a,
|
||||
0x50, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
|
||||
0x00, 0x00, 0x08, 0x70, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x46);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x00, 0x13, 0xf0);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
|
||||
0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
|
||||
0xc0, 0x10);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x53, 0x00, 0x1e,
|
||||
0x1e, 0x77, 0xe1, 0xcc, 0xdd, 0x67, 0x77, 0x33,
|
||||
0x33);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x10, 0x10);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x6c, 0x7c);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0x08, 0x00, 0x0e, 0x00,
|
||||
0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x10,
|
||||
0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
|
||||
0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,
|
||||
0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,
|
||||
0x13, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x80, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x81, 0x88, 0xba, 0x06, 0x42,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x10,
|
||||
0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0b,
|
||||
0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0x0a, 0x0b,
|
||||
0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18, 0x00, 0x07,
|
||||
0x0b, 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0xa0,
|
||||
0x0b, 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18);
|
||||
|
||||
return 0;
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETMIPI, 0x31, 0x81, 0x05, 0xf9,
|
||||
0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00,
|
||||
0x00, 0x02, 0x4f, 0xd1, 0x00, 0x00, 0x37);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER_EXT, 0x25);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETRGBIF, 0x0c, 0x10, 0x0a,
|
||||
0x50, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
|
||||
0x00, 0x00, 0x08, 0x70, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVDC, 0x46);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPANEL, 0x0b);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETCYC, 0x80);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETDISP, 0x00, 0x13, 0xf0);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
|
||||
0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
|
||||
0xc0, 0x10);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETPOWER, 0x53, 0x00, 0x1e,
|
||||
0x1e, 0x77, 0xe1, 0xcc, 0xdd, 0x67, 0x77, 0x33,
|
||||
0x33);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETBGP, 0x10, 0x10);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETVCOM, 0x6c, 0x7c);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP1, 0x08, 0x00, 0x0e, 0x00,
|
||||
0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x10,
|
||||
0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
|
||||
0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,
|
||||
0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,
|
||||
0x13, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x80, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x81, 0x88, 0xba, 0x06, 0x42,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x10,
|
||||
0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(dsi_ctx, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0b,
|
||||
0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0x0a, 0x0b,
|
||||
0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18, 0x00, 0x07,
|
||||
0x0b, 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0xa0,
|
||||
0x0b, 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18);
|
||||
}
|
||||
|
||||
static const struct drm_display_mode gameforcechi_mode = {
|
||||
@ -701,50 +677,37 @@ static int st7703_enable(struct drm_panel *panel)
|
||||
{
|
||||
struct st7703 *ctx = panel_to_st7703(panel);
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
int ret;
|
||||
struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi};
|
||||
|
||||
ret = ctx->desc->init_sequence(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ctx->desc->init_sequence(&dsi_ctx);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
|
||||
|
||||
/* It takes the controller 120 msec to wake up after sleep. */
|
||||
msleep(120);
|
||||
mipi_dsi_msleep(&dsi_ctx, 120);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret)
|
||||
return ret;
|
||||
mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
|
||||
|
||||
dev_dbg(ctx->dev, "Panel init sequence done\n");
|
||||
if (!dsi_ctx.accum_err)
|
||||
dev_dbg(ctx->dev, "Panel init sequence done\n");
|
||||
|
||||
return 0;
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int st7703_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct st7703 *ctx = panel_to_st7703(panel);
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
int ret;
|
||||
struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi};
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret);
|
||||
mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
|
||||
|
||||
/* It takes the controller 120 msec to enter sleep mode. */
|
||||
msleep(120);
|
||||
mipi_dsi_msleep(&dsi_ctx, 120);
|
||||
|
||||
return 0;
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int st7703_unprepare(struct drm_panel *panel)
|
||||
@ -840,10 +803,11 @@ static int allpixelson_set(void *data, u64 val)
|
||||
{
|
||||
struct st7703 *ctx = data;
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
struct mipi_dsi_multi_context dsi_ctx = {.dsi = dsi};
|
||||
|
||||
dev_dbg(ctx->dev, "Setting all pixels on\n");
|
||||
mipi_dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
|
||||
msleep(val * 1000);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, ST7703_CMD_ALL_PIXEL_ON);
|
||||
mipi_dsi_msleep(&dsi_ctx, val * 1000);
|
||||
|
||||
/*
|
||||
* Reset the panel to get video back. NOTE: This isn't a
|
||||
@ -856,7 +820,7 @@ static int allpixelson_set(void *data, u64 val)
|
||||
drm_panel_prepare(&ctx->panel);
|
||||
drm_panel_enable(&ctx->panel);
|
||||
|
||||
return 0;
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL,
|
||||
|
@ -44,248 +44,229 @@ static void truly_nt35521_reset(struct truly_nt35521 *ctx)
|
||||
static int truly_nt35521_on(struct truly_nt35521 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xff, 0xaa, 0x55, 0xa5, 0x80);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x11, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf7, 0x20, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x21);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb8, 0x01, 0x02, 0x0c, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbb, 0x11, 0x11);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb6, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x09, 0x09);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x09, 0x09);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbc, 0x8c, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbd, 0x8c, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xca, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc0, 0x04);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbe, 0xb5);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb3, 0x35, 0x35);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb4, 0x25, 0x25);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb9, 0x43, 0x43);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xba, 0x24, 0x24);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xee, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0,
|
||||
0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3,
|
||||
0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1,
|
||||
0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3,
|
||||
0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb2,
|
||||
0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c,
|
||||
0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb3, 0x03, 0x96, 0x03, 0x98);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb4,
|
||||
0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9,
|
||||
0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb5,
|
||||
0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf,
|
||||
0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb6,
|
||||
0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,
|
||||
0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb7, 0x03, 0xb8, 0x03, 0xba);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb8,
|
||||
0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,
|
||||
0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb9,
|
||||
0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,
|
||||
0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xba,
|
||||
0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,
|
||||
0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbb, 0x03, 0xf6, 0x03, 0xf7);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x22, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x22, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc0, 0x00, 0x34, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc1, 0x00, 0x00, 0x34, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc2, 0x00, 0x00, 0x34, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc3, 0x00, 0x00, 0x34, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc4, 0x60);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc5, 0xc0);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc6, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc7, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb2, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb3, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb4, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb5, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb6, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb7, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb8, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb9, 0x00, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xba, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbb, 0x02, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbc, 0x02, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc0, 0x0b);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc1, 0x09);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc2, 0xa6);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc3, 0x05);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc4, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc5, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc6, 0x22);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc7, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc8, 0x07, 0x20);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc9, 0x03, 0x20);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xca, 0x01, 0x60);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcb, 0x01, 0x60);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcc, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcd, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xce, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcf, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd5,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd6,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd7,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe5, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe6, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe7, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe8, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe9, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xea, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xeb, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xec, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xed, 0x30);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb2, 0x2d, 0x2e);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb3, 0x31, 0x34);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb4, 0x29, 0x2a);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb5, 0x12, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb6, 0x18, 0x16);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb7, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb8, 0x08, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb9, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xba, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbb, 0x31, 0x08);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbc, 0x03, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbd, 0x17, 0x19);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbe, 0x11, 0x13);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xbf, 0x2a, 0x29);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc0, 0x34, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc1, 0x2e, 0x2d);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc2, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc3, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc4, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc5, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc6, 0x2e, 0x2d);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc7, 0x31, 0x34);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc8, 0x29, 0x2a);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc9, 0x17, 0x19);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xca, 0x11, 0x13);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcb, 0x03, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcc, 0x08, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcd, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xce, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xcf, 0x31, 0x08);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd0, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd1, 0x12, 0x10);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd2, 0x18, 0x16);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd3, 0x2a, 0x29);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd4, 0x34, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd5, 0x2d, 0x2e);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd6, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd7, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe5, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe6, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xe7, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf7, 0x47);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x0a);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf7, 0x02);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x17);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf4, 0x60);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf9, 0x46);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x6f, 0x11);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf3, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x35, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd9, 0x02, 0x03, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb1, 0x6c, 0x21);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x35, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x80);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x11, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x20, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x21);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x01, 0x02, 0x0c, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x11, 0x11);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x09, 0x09);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x09, 0x09);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x8c, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x8c, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x04);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbe, 0xb5);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x35, 0x35);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x25, 0x25);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x43, 0x43);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x24, 0x24);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xee, 0x03);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0,
|
||||
0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3,
|
||||
0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1,
|
||||
0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3,
|
||||
0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2,
|
||||
0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c,
|
||||
0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x03, 0x96, 0x03, 0x98);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4,
|
||||
0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9,
|
||||
0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5,
|
||||
0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf,
|
||||
0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6,
|
||||
0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,
|
||||
0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x03, 0xb8, 0x03, 0xba);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8,
|
||||
0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,
|
||||
0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9,
|
||||
0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,
|
||||
0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba,
|
||||
0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,
|
||||
0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x03, 0xf6, 0x03, 0xf7);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x22, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x22, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x00, 0x34, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x00, 0x00, 0x34, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0x00, 0x00, 0x34, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x00, 0x00, 0x34, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x60);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0xc0);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x17, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x00, 0x03);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x02, 0x03);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x02, 0x03);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x0b);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x09);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0xa6);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x05);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x22);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x03);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc8, 0x07, 0x20);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc9, 0x03, 0x20);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x01, 0x60);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, 0x01, 0x60);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcd, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, 0x00, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd5,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd6,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd7,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe5, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe6, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe7, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe8, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe9, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xea, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xeb, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xec, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xed, 0x30);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x2d, 0x2e);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x31, 0x34);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x29, 0x2a);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x12, 0x10);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x18, 0x16);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x08, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x31, 0x08);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x03, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x17, 0x19);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbe, 0x11, 0x13);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbf, 0x2a, 0x29);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x34, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x2e, 0x2d);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x2e, 0x2d);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x31, 0x34);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc8, 0x29, 0x2a);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc9, 0x17, 0x19);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x11, 0x13);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, 0x03, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, 0x08, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcd, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, 0x31, 0x08);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd0, 0x00, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd1, 0x12, 0x10);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd2, 0x18, 0x16);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd3, 0x2a, 0x29);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd4, 0x34, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd5, 0x2d, 0x2e);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd6, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd7, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe5, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe6, 0x31, 0x31);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe7, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x47);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x0a);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x02);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x17);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf4, 0x60);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf9, 0x46);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x11);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf3, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x35, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd9, 0x02, 0x03, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x6c, 0x21);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x35, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(120);
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 120);
|
||||
mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
mipi_dsi_generic_write_seq(dsi, 0x53, 0x24);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x53, 0x24);
|
||||
|
||||
return 0;
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int truly_nt35521_off(struct truly_nt35521 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
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(50);
|
||||
mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 50);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 150);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(150);
|
||||
|
||||
return 0;
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int truly_nt35521_prepare(struct drm_panel *panel)
|
||||
|
@ -236,6 +236,9 @@ static int qxl_add_mode(struct drm_connector *connector,
|
||||
return 0;
|
||||
|
||||
mode = drm_cvt_mode(dev, width, height, 60, false, false, false);
|
||||
if (!mode)
|
||||
return 0;
|
||||
|
||||
if (preferred)
|
||||
mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
mode->hdisplay = width;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/clk.h>
|
||||
@ -92,7 +93,7 @@ static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dp_poweron_start(struct analogix_dp_plat_data *plat_data)
|
||||
static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
|
||||
{
|
||||
struct rockchip_dp_device *dp = pdata_encoder_to_dp(plat_data);
|
||||
int ret;
|
||||
@ -397,7 +398,7 @@ static int rockchip_dp_probe(struct platform_device *pdev)
|
||||
dp->data = dp_data;
|
||||
dp->plat_data.panel = panel;
|
||||
dp->plat_data.dev_type = dp->data->chip_type;
|
||||
dp->plat_data.power_on_start = rockchip_dp_poweron_start;
|
||||
dp->plat_data.power_on = rockchip_dp_poweron;
|
||||
dp->plat_data.power_off = rockchip_dp_powerdown;
|
||||
dp->plat_data.get_modes = rockchip_dp_get_modes;
|
||||
|
||||
@ -413,24 +414,16 @@ static int rockchip_dp_probe(struct platform_device *pdev)
|
||||
|
||||
ret = component_add(dev, &rockchip_dp_component_ops);
|
||||
if (ret)
|
||||
goto err_dp_remove;
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
err_dp_remove:
|
||||
analogix_dp_remove(dp->adp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rockchip_dp_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rockchip_dp_device *dp = platform_get_drvdata(pdev);
|
||||
|
||||
component_del(&pdev->dev, &rockchip_dp_component_ops);
|
||||
analogix_dp_remove(dp->adp);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int rockchip_dp_suspend(struct device *dev)
|
||||
{
|
||||
struct rockchip_dp_device *dp = dev_get_drvdata(dev);
|
||||
@ -450,14 +443,9 @@ static int rockchip_dp_resume(struct device *dev)
|
||||
|
||||
return analogix_dp_resume(dp->adp);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops rockchip_dp_pm_ops = {
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.suspend_late = rockchip_dp_suspend,
|
||||
.resume_early = rockchip_dp_resume,
|
||||
#endif
|
||||
};
|
||||
static DEFINE_RUNTIME_DEV_PM_OPS(rockchip_dp_pm_ops, rockchip_dp_suspend,
|
||||
rockchip_dp_resume, NULL);
|
||||
|
||||
static const struct rockchip_dp_chip_data rk3399_edp = {
|
||||
.lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
|
||||
@ -485,7 +473,7 @@ struct platform_driver rockchip_dp_driver = {
|
||||
.remove_new = rockchip_dp_remove,
|
||||
.driver = {
|
||||
.name = "rockchip-dp",
|
||||
.pm = &rockchip_dp_pm_ops,
|
||||
.pm = pm_ptr(&rockchip_dp_pm_ops),
|
||||
.of_match_table = rockchip_dp_dt_ids,
|
||||
},
|
||||
};
|
||||
|
@ -1740,4 +1740,5 @@ kunit_test_suites(
|
||||
);
|
||||
|
||||
MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
|
||||
MODULE_DESCRIPTION("Kunit test for drm_hdmi_state_helper functions");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -1,4 +1,3 @@
|
||||
CONFIG_KUNIT=y
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_KUNIT_TEST_HELPERS=y
|
||||
CONFIG_DRM_TTM_KUNIT_TEST=y
|
||||
|
@ -6,4 +6,6 @@ obj-$(CONFIG_DRM_TTM_KUNIT_TEST) += \
|
||||
ttm_resource_test.o \
|
||||
ttm_tt_test.o \
|
||||
ttm_bo_test.o \
|
||||
ttm_bo_validate_test.o \
|
||||
ttm_mock_manager.o \
|
||||
ttm_kunit_helpers.o
|
||||
|
27
drivers/gpu/drm/ttm/tests/TODO
Normal file
27
drivers/gpu/drm/ttm/tests/TODO
Normal file
@ -0,0 +1,27 @@
|
||||
TODO
|
||||
=====
|
||||
|
||||
- Add a test case where the only evictable BO is busy
|
||||
- Update eviction tests so they use parametrized "from" memory type
|
||||
- Improve mock manager's implementation, e.g. allocate a block of
|
||||
dummy memory that can be used when testing page mapping functions
|
||||
- Suggestion: Add test cases with external BOs
|
||||
- Suggestion: randomize the number and size of tested buffers in
|
||||
ttm_bo_validate()
|
||||
- Agree on the naming convention
|
||||
- Rewrite the mock manager: drop use_tt and manage mock memory using
|
||||
drm_mm manager
|
||||
|
||||
Notes and gotchas
|
||||
=================
|
||||
|
||||
- These tests are built and run with a UML kernel, because
|
||||
1) We are interested in hardware-independent testing
|
||||
2) We don't want to have actual DRM devices interacting with TTM
|
||||
at the same time as the test one. Getting these to work in
|
||||
parallel would require some time (...and that's a "todo" in itself!)
|
||||
- Triggering ttm_bo_vm_ops callbacks from KUnit (i.e. kernel) might be
|
||||
a challenge, but is worth trying. Look at selftests like
|
||||
i915/gem/selftests/i915_gem_mman.c for inspiration
|
||||
- The test suite uses UML where ioremap() call returns NULL, meaning that
|
||||
ttm_bo_ioremap() can't be tested, unless we find a way to stub it
|
@ -18,6 +18,12 @@
|
||||
|
||||
#define BO_SIZE SZ_8K
|
||||
|
||||
#ifdef CONFIG_PREEMPT_RT
|
||||
#define ww_mutex_base_lock(b) rt_mutex_lock(b)
|
||||
#else
|
||||
#define ww_mutex_base_lock(b) mutex_lock(b)
|
||||
#endif
|
||||
|
||||
struct ttm_bo_test_case {
|
||||
const char *description;
|
||||
bool interruptible;
|
||||
@ -56,7 +62,7 @@ static void ttm_bo_reserve_optimistic_no_ticket(struct kunit *test)
|
||||
struct ttm_buffer_object *bo;
|
||||
int err;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
err = ttm_bo_reserve(bo, params->interruptible, params->no_wait, NULL);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
@ -71,7 +77,7 @@ static void ttm_bo_reserve_locked_no_sleep(struct kunit *test)
|
||||
bool no_wait = true;
|
||||
int err;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
/* Let's lock it beforehand */
|
||||
dma_resv_lock(bo->base.resv, NULL);
|
||||
@ -92,7 +98,7 @@ static void ttm_bo_reserve_no_wait_ticket(struct kunit *test)
|
||||
|
||||
ww_acquire_init(&ctx, &reservation_ww_class);
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
|
||||
KUNIT_ASSERT_EQ(test, err, -EBUSY);
|
||||
@ -110,7 +116,7 @@ static void ttm_bo_reserve_double_resv(struct kunit *test)
|
||||
|
||||
ww_acquire_init(&ctx, &reservation_ww_class);
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
err = ttm_bo_reserve(bo, interruptible, no_wait, &ctx);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
@ -138,11 +144,11 @@ static void ttm_bo_reserve_deadlock(struct kunit *test)
|
||||
bool no_wait = false;
|
||||
int err;
|
||||
|
||||
bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
ww_acquire_init(&ctx1, &reservation_ww_class);
|
||||
mutex_lock(&bo2->base.resv->lock.base);
|
||||
ww_mutex_base_lock(&bo2->base.resv->lock.base);
|
||||
|
||||
/* The deadlock will be caught by WW mutex, don't warn about it */
|
||||
lock_release(&bo2->base.resv->lock.base.dep_map, 1);
|
||||
@ -208,7 +214,7 @@ static void ttm_bo_reserve_interrupted(struct kunit *test)
|
||||
struct task_struct *task;
|
||||
int err;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
task = kthread_create(threaded_ttm_bo_reserve, bo, "ttm-bo-reserve");
|
||||
|
||||
@ -237,7 +243,7 @@ static void ttm_bo_unreserve_basic(struct kunit *test)
|
||||
struct ttm_place *place;
|
||||
struct ttm_resource_manager *man;
|
||||
unsigned int bo_prio = TTM_MAX_BO_PRIORITY - 1;
|
||||
uint32_t mem_type = TTM_PL_SYSTEM;
|
||||
u32 mem_type = TTM_PL_SYSTEM;
|
||||
int err;
|
||||
|
||||
place = ttm_place_kunit_init(test, mem_type, 0);
|
||||
@ -249,7 +255,7 @@ static void ttm_bo_unreserve_basic(struct kunit *test)
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
priv->ttm_dev = ttm_dev;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
bo->priority = bo_prio;
|
||||
|
||||
err = ttm_resource_alloc(bo, place, &res1);
|
||||
@ -278,7 +284,7 @@ static void ttm_bo_unreserve_pinned(struct kunit *test)
|
||||
struct ttm_device *ttm_dev;
|
||||
struct ttm_resource *res1, *res2;
|
||||
struct ttm_place *place;
|
||||
uint32_t mem_type = TTM_PL_SYSTEM;
|
||||
u32 mem_type = TTM_PL_SYSTEM;
|
||||
int err;
|
||||
|
||||
ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
|
||||
@ -288,7 +294,7 @@ static void ttm_bo_unreserve_pinned(struct kunit *test)
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
priv->ttm_dev = ttm_dev;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
place = ttm_place_kunit_init(test, mem_type, 0);
|
||||
|
||||
dma_resv_lock(bo->base.resv, NULL);
|
||||
@ -321,7 +327,8 @@ static void ttm_bo_unreserve_bulk(struct kunit *test)
|
||||
struct ttm_resource *res1, *res2;
|
||||
struct ttm_device *ttm_dev;
|
||||
struct ttm_place *place;
|
||||
uint32_t mem_type = TTM_PL_SYSTEM;
|
||||
struct dma_resv *resv;
|
||||
u32 mem_type = TTM_PL_SYSTEM;
|
||||
unsigned int bo_priority = 0;
|
||||
int err;
|
||||
|
||||
@ -332,12 +339,17 @@ static void ttm_bo_unreserve_bulk(struct kunit *test)
|
||||
ttm_dev = kunit_kzalloc(test, sizeof(*ttm_dev), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
|
||||
|
||||
resv = kunit_kzalloc(test, sizeof(*resv), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, ttm_dev);
|
||||
|
||||
err = ttm_device_kunit_init(priv, ttm_dev, false, false);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
priv->ttm_dev = ttm_dev;
|
||||
|
||||
bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
dma_resv_init(resv);
|
||||
|
||||
bo1 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, resv);
|
||||
bo2 = ttm_bo_kunit_init(test, test->priv, BO_SIZE, resv);
|
||||
|
||||
dma_resv_lock(bo1->base.resv, NULL);
|
||||
ttm_bo_set_bulk_move(bo1, &lru_bulk_move);
|
||||
@ -363,6 +375,8 @@ static void ttm_bo_unreserve_bulk(struct kunit *test)
|
||||
|
||||
ttm_resource_free(bo1, &res1);
|
||||
ttm_resource_free(bo2, &res2);
|
||||
|
||||
dma_resv_fini(resv);
|
||||
}
|
||||
|
||||
static void ttm_bo_put_basic(struct kunit *test)
|
||||
@ -372,7 +386,7 @@ static void ttm_bo_put_basic(struct kunit *test)
|
||||
struct ttm_resource *res;
|
||||
struct ttm_device *ttm_dev;
|
||||
struct ttm_place *place;
|
||||
uint32_t mem_type = TTM_PL_SYSTEM;
|
||||
u32 mem_type = TTM_PL_SYSTEM;
|
||||
int err;
|
||||
|
||||
place = ttm_place_kunit_init(test, mem_type, 0);
|
||||
@ -384,7 +398,7 @@ static void ttm_bo_put_basic(struct kunit *test)
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
priv->ttm_dev = ttm_dev;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
bo->type = ttm_bo_type_device;
|
||||
|
||||
err = ttm_resource_alloc(bo, place, &res);
|
||||
@ -445,7 +459,7 @@ static void ttm_bo_put_shared_resv(struct kunit *test)
|
||||
|
||||
dma_fence_signal(fence);
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
bo->type = ttm_bo_type_device;
|
||||
bo->base.resv = external_resv;
|
||||
|
||||
@ -467,7 +481,7 @@ static void ttm_bo_pin_basic(struct kunit *test)
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
priv->ttm_dev = ttm_dev;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
for (int i = 0; i < no_pins; i++) {
|
||||
dma_resv_lock(bo->base.resv, NULL);
|
||||
@ -487,7 +501,7 @@ static void ttm_bo_pin_unpin_resource(struct kunit *test)
|
||||
struct ttm_resource *res;
|
||||
struct ttm_device *ttm_dev;
|
||||
struct ttm_place *place;
|
||||
uint32_t mem_type = TTM_PL_SYSTEM;
|
||||
u32 mem_type = TTM_PL_SYSTEM;
|
||||
unsigned int bo_priority = 0;
|
||||
int err;
|
||||
|
||||
@ -502,7 +516,7 @@ static void ttm_bo_pin_unpin_resource(struct kunit *test)
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
priv->ttm_dev = ttm_dev;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
err = ttm_resource_alloc(bo, place, &res);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
@ -538,7 +552,7 @@ static void ttm_bo_multiple_pin_one_unpin(struct kunit *test)
|
||||
struct ttm_resource *res;
|
||||
struct ttm_device *ttm_dev;
|
||||
struct ttm_place *place;
|
||||
uint32_t mem_type = TTM_PL_SYSTEM;
|
||||
u32 mem_type = TTM_PL_SYSTEM;
|
||||
unsigned int bo_priority = 0;
|
||||
int err;
|
||||
|
||||
@ -553,7 +567,7 @@ static void ttm_bo_multiple_pin_one_unpin(struct kunit *test)
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
priv->ttm_dev = ttm_dev;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
err = ttm_resource_alloc(bo, place, &res);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
@ -619,4 +633,5 @@ static struct kunit_suite ttm_bo_test_suite = {
|
||||
|
||||
kunit_test_suites(&ttm_bo_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("KUnit tests for ttm_bo APIs");
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
1225
drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
Normal file
1225
drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -209,4 +209,5 @@ static struct kunit_suite ttm_device_test_suite = {
|
||||
|
||||
kunit_test_suites(&ttm_device_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("KUnit tests for ttm_device APIs");
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
@ -6,8 +6,43 @@
|
||||
|
||||
#include "ttm_kunit_helpers.h"
|
||||
|
||||
static struct ttm_tt *ttm_tt_simple_create(struct ttm_buffer_object *bo,
|
||||
uint32_t page_flags)
|
||||
static const struct ttm_place sys_place = {
|
||||
.fpfn = 0,
|
||||
.lpfn = 0,
|
||||
.mem_type = TTM_PL_SYSTEM,
|
||||
.flags = TTM_PL_FLAG_FALLBACK,
|
||||
};
|
||||
|
||||
static const struct ttm_place mock1_place = {
|
||||
.fpfn = 0,
|
||||
.lpfn = 0,
|
||||
.mem_type = TTM_PL_MOCK1,
|
||||
.flags = TTM_PL_FLAG_FALLBACK,
|
||||
};
|
||||
|
||||
static const struct ttm_place mock2_place = {
|
||||
.fpfn = 0,
|
||||
.lpfn = 0,
|
||||
.mem_type = TTM_PL_MOCK2,
|
||||
.flags = TTM_PL_FLAG_FALLBACK,
|
||||
};
|
||||
|
||||
static struct ttm_placement sys_placement = {
|
||||
.num_placement = 1,
|
||||
.placement = &sys_place,
|
||||
};
|
||||
|
||||
static struct ttm_placement bad_placement = {
|
||||
.num_placement = 1,
|
||||
.placement = &mock1_place,
|
||||
};
|
||||
|
||||
static struct ttm_placement mock_placement = {
|
||||
.num_placement = 1,
|
||||
.placement = &mock2_place,
|
||||
};
|
||||
|
||||
static struct ttm_tt *ttm_tt_simple_create(struct ttm_buffer_object *bo, u32 page_flags)
|
||||
{
|
||||
struct ttm_tt *tt;
|
||||
|
||||
@ -22,13 +57,84 @@ static void ttm_tt_simple_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
|
||||
kfree(ttm);
|
||||
}
|
||||
|
||||
static void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo)
|
||||
static int mock_move(struct ttm_buffer_object *bo, bool evict,
|
||||
struct ttm_operation_ctx *ctx,
|
||||
struct ttm_resource *new_mem,
|
||||
struct ttm_place *hop)
|
||||
{
|
||||
struct ttm_resource *old_mem = bo->resource;
|
||||
|
||||
if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm)) {
|
||||
ttm_bo_move_null(bo, new_mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bo->resource->mem_type == TTM_PL_VRAM &&
|
||||
new_mem->mem_type == TTM_PL_SYSTEM) {
|
||||
hop->mem_type = TTM_PL_TT;
|
||||
hop->flags = TTM_PL_FLAG_TEMPORARY;
|
||||
hop->fpfn = 0;
|
||||
hop->lpfn = 0;
|
||||
return -EMULTIHOP;
|
||||
}
|
||||
|
||||
if ((old_mem->mem_type == TTM_PL_SYSTEM &&
|
||||
new_mem->mem_type == TTM_PL_TT) ||
|
||||
(old_mem->mem_type == TTM_PL_TT &&
|
||||
new_mem->mem_type == TTM_PL_SYSTEM)) {
|
||||
ttm_bo_move_null(bo, new_mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ttm_bo_move_memcpy(bo, ctx, new_mem);
|
||||
}
|
||||
|
||||
static void mock_evict_flags(struct ttm_buffer_object *bo,
|
||||
struct ttm_placement *placement)
|
||||
{
|
||||
switch (bo->resource->mem_type) {
|
||||
case TTM_PL_VRAM:
|
||||
case TTM_PL_SYSTEM:
|
||||
*placement = sys_placement;
|
||||
break;
|
||||
case TTM_PL_TT:
|
||||
*placement = mock_placement;
|
||||
break;
|
||||
case TTM_PL_MOCK1:
|
||||
/* Purge objects coming from this domain */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void bad_evict_flags(struct ttm_buffer_object *bo,
|
||||
struct ttm_placement *placement)
|
||||
{
|
||||
*placement = bad_placement;
|
||||
}
|
||||
|
||||
static int ttm_device_kunit_init_with_funcs(struct ttm_test_devices *priv,
|
||||
struct ttm_device *ttm,
|
||||
bool use_dma_alloc,
|
||||
bool use_dma32,
|
||||
struct ttm_device_funcs *funcs)
|
||||
{
|
||||
struct drm_device *drm = priv->drm;
|
||||
int err;
|
||||
|
||||
err = ttm_device_init(ttm, funcs, drm->dev,
|
||||
drm->anon_inode->i_mapping,
|
||||
drm->vma_offset_manager,
|
||||
use_dma_alloc, use_dma32);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
struct ttm_device_funcs ttm_dev_funcs = {
|
||||
.ttm_tt_create = ttm_tt_simple_create,
|
||||
.ttm_tt_destroy = ttm_tt_simple_destroy,
|
||||
.move = mock_move,
|
||||
.eviction_valuable = ttm_bo_eviction_valuable,
|
||||
.evict_flags = mock_evict_flags,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ttm_dev_funcs);
|
||||
|
||||
@ -37,21 +143,34 @@ int ttm_device_kunit_init(struct ttm_test_devices *priv,
|
||||
bool use_dma_alloc,
|
||||
bool use_dma32)
|
||||
{
|
||||
struct drm_device *drm = priv->drm;
|
||||
int err;
|
||||
|
||||
err = ttm_device_init(ttm, &ttm_dev_funcs, drm->dev,
|
||||
drm->anon_inode->i_mapping,
|
||||
drm->vma_offset_manager,
|
||||
use_dma_alloc, use_dma32);
|
||||
|
||||
return err;
|
||||
return ttm_device_kunit_init_with_funcs(priv, ttm, use_dma_alloc,
|
||||
use_dma32, &ttm_dev_funcs);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_device_kunit_init);
|
||||
|
||||
struct ttm_device_funcs ttm_dev_funcs_bad_evict = {
|
||||
.ttm_tt_create = ttm_tt_simple_create,
|
||||
.ttm_tt_destroy = ttm_tt_simple_destroy,
|
||||
.move = mock_move,
|
||||
.eviction_valuable = ttm_bo_eviction_valuable,
|
||||
.evict_flags = bad_evict_flags,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ttm_dev_funcs_bad_evict);
|
||||
|
||||
int ttm_device_kunit_init_bad_evict(struct ttm_test_devices *priv,
|
||||
struct ttm_device *ttm,
|
||||
bool use_dma_alloc,
|
||||
bool use_dma32)
|
||||
{
|
||||
return ttm_device_kunit_init_with_funcs(priv, ttm, use_dma_alloc,
|
||||
use_dma32, &ttm_dev_funcs_bad_evict);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_device_kunit_init_bad_evict);
|
||||
|
||||
struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
|
||||
struct ttm_test_devices *devs,
|
||||
size_t size)
|
||||
size_t size,
|
||||
struct dma_resv *obj)
|
||||
{
|
||||
struct drm_gem_object gem_obj = { };
|
||||
struct ttm_buffer_object *bo;
|
||||
@ -61,6 +180,10 @@ struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
|
||||
KUNIT_ASSERT_NOT_NULL(test, bo);
|
||||
|
||||
bo->base = gem_obj;
|
||||
|
||||
if (obj)
|
||||
bo->base.resv = obj;
|
||||
|
||||
err = drm_gem_object_init(devs->drm, &bo->base, size);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
|
||||
@ -73,8 +196,7 @@ struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_bo_kunit_init);
|
||||
|
||||
struct ttm_place *ttm_place_kunit_init(struct kunit *test,
|
||||
uint32_t mem_type, uint32_t flags)
|
||||
struct ttm_place *ttm_place_kunit_init(struct kunit *test, u32 mem_type, u32 flags)
|
||||
{
|
||||
struct ttm_place *place;
|
||||
|
||||
@ -88,6 +210,12 @@ struct ttm_place *ttm_place_kunit_init(struct kunit *test,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_place_kunit_init);
|
||||
|
||||
void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo)
|
||||
{
|
||||
drm_gem_object_release(&bo->base);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dummy_ttm_bo_destroy);
|
||||
|
||||
struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test)
|
||||
{
|
||||
struct ttm_test_devices *devs;
|
||||
@ -98,6 +226,9 @@ struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test)
|
||||
devs->dev = drm_kunit_helper_alloc_device(test);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, devs->dev);
|
||||
|
||||
/* Set mask for alloc_coherent mappings to enable ttm_pool_alloc testing */
|
||||
devs->dev->coherent_dma_mask = -1;
|
||||
|
||||
devs->drm = __drm_kunit_helper_alloc_drm_device(test, devs->dev,
|
||||
sizeof(*devs->drm), 0,
|
||||
DRIVER_GEM);
|
||||
@ -150,10 +281,25 @@ int ttm_test_devices_init(struct kunit *test)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_test_devices_init);
|
||||
|
||||
int ttm_test_devices_all_init(struct kunit *test)
|
||||
{
|
||||
struct ttm_test_devices *priv;
|
||||
|
||||
priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, priv);
|
||||
|
||||
priv = ttm_test_devices_all(test);
|
||||
test->priv = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_test_devices_all_init);
|
||||
|
||||
void ttm_test_devices_fini(struct kunit *test)
|
||||
{
|
||||
ttm_test_devices_put(test, test->priv);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_test_devices_fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("TTM KUnit test helper functions");
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
@ -13,7 +13,11 @@
|
||||
#include <drm/drm_kunit_helpers.h>
|
||||
#include <kunit/test.h>
|
||||
|
||||
#define TTM_PL_MOCK1 (TTM_PL_PRIV + 1)
|
||||
#define TTM_PL_MOCK2 (TTM_PL_PRIV + 2)
|
||||
|
||||
extern struct ttm_device_funcs ttm_dev_funcs;
|
||||
extern struct ttm_device_funcs ttm_dev_funcs_bad_evict;
|
||||
|
||||
struct ttm_test_devices {
|
||||
struct drm_device *drm;
|
||||
@ -26,11 +30,17 @@ int ttm_device_kunit_init(struct ttm_test_devices *priv,
|
||||
struct ttm_device *ttm,
|
||||
bool use_dma_alloc,
|
||||
bool use_dma32);
|
||||
int ttm_device_kunit_init_bad_evict(struct ttm_test_devices *priv,
|
||||
struct ttm_device *ttm,
|
||||
bool use_dma_alloc,
|
||||
bool use_dma32);
|
||||
struct ttm_buffer_object *ttm_bo_kunit_init(struct kunit *test,
|
||||
struct ttm_test_devices *devs,
|
||||
size_t size);
|
||||
struct ttm_place *ttm_place_kunit_init(struct kunit *test,
|
||||
uint32_t mem_type, uint32_t flags);
|
||||
size_t size,
|
||||
struct dma_resv *obj);
|
||||
struct ttm_place *ttm_place_kunit_init(struct kunit *test, u32 mem_type,
|
||||
u32 flags);
|
||||
void dummy_ttm_bo_destroy(struct ttm_buffer_object *bo);
|
||||
|
||||
struct ttm_test_devices *ttm_test_devices_basic(struct kunit *test);
|
||||
struct ttm_test_devices *ttm_test_devices_all(struct kunit *test);
|
||||
@ -39,6 +49,7 @@ void ttm_test_devices_put(struct kunit *test, struct ttm_test_devices *devs);
|
||||
|
||||
/* Generic init/fini for tests that only need DRM/TTM devices */
|
||||
int ttm_test_devices_init(struct kunit *test);
|
||||
int ttm_test_devices_all_init(struct kunit *test);
|
||||
void ttm_test_devices_fini(struct kunit *test);
|
||||
|
||||
#endif // TTM_KUNIT_HELPERS_H
|
||||
|
234
drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
Normal file
234
drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
Normal file
@ -0,0 +1,234 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 AND MIT
|
||||
/*
|
||||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
#include <drm/ttm/ttm_resource.h>
|
||||
#include <drm/ttm/ttm_device.h>
|
||||
#include <drm/ttm/ttm_placement.h>
|
||||
|
||||
#include "ttm_mock_manager.h"
|
||||
|
||||
static inline struct ttm_mock_manager *
|
||||
to_mock_mgr(struct ttm_resource_manager *man)
|
||||
{
|
||||
return container_of(man, struct ttm_mock_manager, man);
|
||||
}
|
||||
|
||||
static inline struct ttm_mock_resource *
|
||||
to_mock_mgr_resource(struct ttm_resource *res)
|
||||
{
|
||||
return container_of(res, struct ttm_mock_resource, base);
|
||||
}
|
||||
|
||||
static int ttm_mock_manager_alloc(struct ttm_resource_manager *man,
|
||||
struct ttm_buffer_object *bo,
|
||||
const struct ttm_place *place,
|
||||
struct ttm_resource **res)
|
||||
{
|
||||
struct ttm_mock_manager *manager = to_mock_mgr(man);
|
||||
struct ttm_mock_resource *mock_res;
|
||||
struct drm_buddy *mm = &manager->mm;
|
||||
u64 lpfn, fpfn, alloc_size;
|
||||
int err;
|
||||
|
||||
mock_res = kzalloc(sizeof(*mock_res), GFP_KERNEL);
|
||||
|
||||
if (!mock_res)
|
||||
return -ENOMEM;
|
||||
|
||||
fpfn = 0;
|
||||
lpfn = man->size;
|
||||
|
||||
ttm_resource_init(bo, place, &mock_res->base);
|
||||
INIT_LIST_HEAD(&mock_res->blocks);
|
||||
|
||||
if (place->flags & TTM_PL_FLAG_TOPDOWN)
|
||||
mock_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
|
||||
|
||||
if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
|
||||
mock_res->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION;
|
||||
|
||||
alloc_size = (uint64_t)mock_res->base.size;
|
||||
mutex_lock(&manager->lock);
|
||||
err = drm_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size,
|
||||
manager->default_page_size,
|
||||
&mock_res->blocks,
|
||||
mock_res->flags);
|
||||
|
||||
if (err)
|
||||
goto error_free_blocks;
|
||||
mutex_unlock(&manager->lock);
|
||||
|
||||
*res = &mock_res->base;
|
||||
return 0;
|
||||
|
||||
error_free_blocks:
|
||||
drm_buddy_free_list(mm, &mock_res->blocks, 0);
|
||||
ttm_resource_fini(man, &mock_res->base);
|
||||
mutex_unlock(&manager->lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ttm_mock_manager_free(struct ttm_resource_manager *man,
|
||||
struct ttm_resource *res)
|
||||
{
|
||||
struct ttm_mock_manager *manager = to_mock_mgr(man);
|
||||
struct ttm_mock_resource *mock_res = to_mock_mgr_resource(res);
|
||||
struct drm_buddy *mm = &manager->mm;
|
||||
|
||||
mutex_lock(&manager->lock);
|
||||
drm_buddy_free_list(mm, &mock_res->blocks, 0);
|
||||
mutex_unlock(&manager->lock);
|
||||
|
||||
ttm_resource_fini(man, res);
|
||||
kfree(mock_res);
|
||||
}
|
||||
|
||||
static const struct ttm_resource_manager_func ttm_mock_manager_funcs = {
|
||||
.alloc = ttm_mock_manager_alloc,
|
||||
.free = ttm_mock_manager_free,
|
||||
};
|
||||
|
||||
int ttm_mock_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size)
|
||||
{
|
||||
struct ttm_mock_manager *manager;
|
||||
struct ttm_resource_manager *base;
|
||||
int err;
|
||||
|
||||
manager = kzalloc(sizeof(*manager), GFP_KERNEL);
|
||||
if (!manager)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&manager->lock);
|
||||
|
||||
err = drm_buddy_init(&manager->mm, size, PAGE_SIZE);
|
||||
|
||||
if (err) {
|
||||
kfree(manager);
|
||||
return err;
|
||||
}
|
||||
|
||||
manager->default_page_size = PAGE_SIZE;
|
||||
base = &manager->man;
|
||||
base->func = &ttm_mock_manager_funcs;
|
||||
base->use_tt = true;
|
||||
|
||||
ttm_resource_manager_init(base, bdev, size);
|
||||
ttm_set_driver_manager(bdev, mem_type, base);
|
||||
ttm_resource_manager_set_used(base, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_mock_manager_init);
|
||||
|
||||
void ttm_mock_manager_fini(struct ttm_device *bdev, u32 mem_type)
|
||||
{
|
||||
struct ttm_resource_manager *man;
|
||||
struct ttm_mock_manager *mock_man;
|
||||
int err;
|
||||
|
||||
man = ttm_manager_type(bdev, mem_type);
|
||||
mock_man = to_mock_mgr(man);
|
||||
|
||||
err = ttm_resource_manager_evict_all(bdev, man);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
ttm_resource_manager_set_used(man, false);
|
||||
|
||||
mutex_lock(&mock_man->lock);
|
||||
drm_buddy_fini(&mock_man->mm);
|
||||
mutex_unlock(&mock_man->lock);
|
||||
|
||||
ttm_set_driver_manager(bdev, mem_type, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_mock_manager_fini);
|
||||
|
||||
static int ttm_bad_manager_alloc(struct ttm_resource_manager *man,
|
||||
struct ttm_buffer_object *bo,
|
||||
const struct ttm_place *place,
|
||||
struct ttm_resource **res)
|
||||
{
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
static int ttm_busy_manager_alloc(struct ttm_resource_manager *man,
|
||||
struct ttm_buffer_object *bo,
|
||||
const struct ttm_place *place,
|
||||
struct ttm_resource **res)
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static void ttm_bad_manager_free(struct ttm_resource_manager *man,
|
||||
struct ttm_resource *res)
|
||||
{
|
||||
}
|
||||
|
||||
static bool ttm_bad_manager_compatible(struct ttm_resource_manager *man,
|
||||
struct ttm_resource *res,
|
||||
const struct ttm_place *place,
|
||||
size_t size)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct ttm_resource_manager_func ttm_bad_manager_funcs = {
|
||||
.alloc = ttm_bad_manager_alloc,
|
||||
.free = ttm_bad_manager_free,
|
||||
.compatible = ttm_bad_manager_compatible
|
||||
};
|
||||
|
||||
static const struct ttm_resource_manager_func ttm_bad_busy_manager_funcs = {
|
||||
.alloc = ttm_busy_manager_alloc,
|
||||
.free = ttm_bad_manager_free,
|
||||
.compatible = ttm_bad_manager_compatible
|
||||
};
|
||||
|
||||
int ttm_bad_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size)
|
||||
{
|
||||
struct ttm_resource_manager *man;
|
||||
|
||||
man = kzalloc(sizeof(*man), GFP_KERNEL);
|
||||
if (!man)
|
||||
return -ENOMEM;
|
||||
|
||||
man->func = &ttm_bad_manager_funcs;
|
||||
|
||||
ttm_resource_manager_init(man, bdev, size);
|
||||
ttm_set_driver_manager(bdev, mem_type, man);
|
||||
ttm_resource_manager_set_used(man, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_bad_manager_init);
|
||||
|
||||
int ttm_busy_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size)
|
||||
{
|
||||
struct ttm_resource_manager *man;
|
||||
|
||||
ttm_bad_manager_init(bdev, mem_type, size);
|
||||
man = ttm_manager_type(bdev, mem_type);
|
||||
|
||||
man->func = &ttm_bad_busy_manager_funcs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_busy_manager_init);
|
||||
|
||||
void ttm_bad_manager_fini(struct ttm_device *bdev, uint32_t mem_type)
|
||||
{
|
||||
struct ttm_resource_manager *man;
|
||||
|
||||
man = ttm_manager_type(bdev, mem_type);
|
||||
|
||||
ttm_resource_manager_set_used(man, false);
|
||||
ttm_set_driver_manager(bdev, mem_type, NULL);
|
||||
|
||||
kfree(man);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ttm_bad_manager_fini);
|
||||
|
||||
MODULE_DESCRIPTION("KUnit tests for ttm with mock resource managers");
|
||||
MODULE_LICENSE("GPL and additional rights");
|
30
drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
Normal file
30
drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 AND MIT */
|
||||
/*
|
||||
* Copyright © 2023 Intel Corporation
|
||||
*/
|
||||
#ifndef TTM_MOCK_MANAGER_H
|
||||
#define TTM_MOCK_MANAGER_H
|
||||
|
||||
#include <drm/drm_buddy.h>
|
||||
|
||||
struct ttm_mock_manager {
|
||||
struct ttm_resource_manager man;
|
||||
struct drm_buddy mm;
|
||||
u64 default_page_size;
|
||||
/* protects allocations of mock buffer objects */
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
struct ttm_mock_resource {
|
||||
struct ttm_resource base;
|
||||
struct list_head blocks;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
int ttm_mock_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size);
|
||||
int ttm_bad_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size);
|
||||
int ttm_busy_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size);
|
||||
void ttm_mock_manager_fini(struct ttm_device *bdev, u32 mem_type);
|
||||
void ttm_bad_manager_fini(struct ttm_device *bdev, u32 mem_type);
|
||||
|
||||
#endif // TTM_MOCK_MANAGER_H
|
@ -48,7 +48,7 @@ static void ttm_pool_test_fini(struct kunit *test)
|
||||
}
|
||||
|
||||
static struct ttm_tt *ttm_tt_kunit_init(struct kunit *test,
|
||||
uint32_t page_flags,
|
||||
u32 page_flags,
|
||||
enum ttm_caching caching,
|
||||
size_t size)
|
||||
{
|
||||
@ -57,7 +57,7 @@ static struct ttm_tt *ttm_tt_kunit_init(struct kunit *test,
|
||||
struct ttm_tt *tt;
|
||||
int err;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, priv->devs, size);
|
||||
bo = ttm_bo_kunit_init(test, priv->devs, size, NULL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, bo);
|
||||
priv->mock_bo = bo;
|
||||
|
||||
@ -209,7 +209,7 @@ static void ttm_pool_alloc_basic_dma_addr(struct kunit *test)
|
||||
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt);
|
||||
|
||||
bo = ttm_bo_kunit_init(test, devs, size);
|
||||
bo = ttm_bo_kunit_init(test, devs, size, NULL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, bo);
|
||||
|
||||
err = ttm_sg_tt_init(tt, bo, 0, caching);
|
||||
@ -433,4 +433,5 @@ static struct kunit_suite ttm_pool_test_suite = {
|
||||
|
||||
kunit_test_suites(&ttm_pool_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("KUnit tests for ttm_pool APIs");
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
struct ttm_resource_test_case {
|
||||
const char *description;
|
||||
uint32_t mem_type;
|
||||
uint32_t flags;
|
||||
u32 mem_type;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct ttm_resource_test_priv {
|
||||
@ -47,20 +47,20 @@ static void ttm_resource_test_fini(struct kunit *test)
|
||||
|
||||
static void ttm_init_test_mocks(struct kunit *test,
|
||||
struct ttm_resource_test_priv *priv,
|
||||
uint32_t mem_type, uint32_t flags)
|
||||
u32 mem_type, u32 flags)
|
||||
{
|
||||
size_t size = RES_SIZE;
|
||||
|
||||
/* Make sure we have what we need for a good BO mock */
|
||||
KUNIT_ASSERT_NOT_NULL(test, priv->devs->ttm_dev);
|
||||
|
||||
priv->bo = ttm_bo_kunit_init(test, priv->devs, size);
|
||||
priv->bo = ttm_bo_kunit_init(test, priv->devs, size, NULL);
|
||||
priv->place = ttm_place_kunit_init(test, mem_type, flags);
|
||||
}
|
||||
|
||||
static void ttm_init_test_manager(struct kunit *test,
|
||||
struct ttm_resource_test_priv *priv,
|
||||
uint32_t mem_type)
|
||||
u32 mem_type)
|
||||
{
|
||||
struct ttm_device *ttm_dev = priv->devs->ttm_dev;
|
||||
struct ttm_resource_manager *man;
|
||||
@ -112,7 +112,7 @@ static void ttm_resource_init_basic(struct kunit *test)
|
||||
struct ttm_buffer_object *bo;
|
||||
struct ttm_place *place;
|
||||
struct ttm_resource_manager *man;
|
||||
uint64_t expected_usage;
|
||||
u64 expected_usage;
|
||||
|
||||
ttm_init_test_mocks(test, priv, params->mem_type, params->flags);
|
||||
bo = priv->bo;
|
||||
@ -230,7 +230,7 @@ static void ttm_resource_manager_usage_basic(struct kunit *test)
|
||||
struct ttm_buffer_object *bo;
|
||||
struct ttm_place *place;
|
||||
struct ttm_resource_manager *man;
|
||||
uint64_t actual_usage;
|
||||
u64 actual_usage;
|
||||
|
||||
ttm_init_test_mocks(test, priv, TTM_PL_SYSTEM, TTM_PL_FLAG_TOPDOWN);
|
||||
bo = priv->bo;
|
||||
@ -268,7 +268,7 @@ static void ttm_sys_man_alloc_basic(struct kunit *test)
|
||||
struct ttm_buffer_object *bo;
|
||||
struct ttm_place *place;
|
||||
struct ttm_resource *res;
|
||||
uint32_t mem_type = TTM_PL_SYSTEM;
|
||||
u32 mem_type = TTM_PL_SYSTEM;
|
||||
int ret;
|
||||
|
||||
ttm_init_test_mocks(test, priv, mem_type, 0);
|
||||
@ -293,7 +293,7 @@ static void ttm_sys_man_free_basic(struct kunit *test)
|
||||
struct ttm_buffer_object *bo;
|
||||
struct ttm_place *place;
|
||||
struct ttm_resource *res;
|
||||
uint32_t mem_type = TTM_PL_SYSTEM;
|
||||
u32 mem_type = TTM_PL_SYSTEM;
|
||||
|
||||
ttm_init_test_mocks(test, priv, mem_type, 0);
|
||||
bo = priv->bo;
|
||||
@ -332,4 +332,5 @@ static struct kunit_suite ttm_resource_test_suite = {
|
||||
|
||||
kunit_test_suites(&ttm_resource_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("KUnit tests for ttm_resource and ttm_sys_man APIs");
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
@ -11,23 +11,10 @@
|
||||
|
||||
struct ttm_tt_test_case {
|
||||
const char *description;
|
||||
uint32_t size;
|
||||
uint32_t extra_pages_num;
|
||||
u32 size;
|
||||
u32 extra_pages_num;
|
||||
};
|
||||
|
||||
static int ttm_tt_test_init(struct kunit *test)
|
||||
{
|
||||
struct ttm_test_devices *priv;
|
||||
|
||||
priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, priv);
|
||||
|
||||
priv = ttm_test_devices_all(test);
|
||||
test->priv = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ttm_tt_test_case ttm_tt_init_basic_cases[] = {
|
||||
{
|
||||
.description = "Page-aligned size",
|
||||
@ -54,16 +41,16 @@ static void ttm_tt_init_basic(struct kunit *test)
|
||||
const struct ttm_tt_test_case *params = test->param_value;
|
||||
struct ttm_buffer_object *bo;
|
||||
struct ttm_tt *tt;
|
||||
uint32_t page_flags = TTM_TT_FLAG_ZERO_ALLOC;
|
||||
u32 page_flags = TTM_TT_FLAG_ZERO_ALLOC;
|
||||
enum ttm_caching caching = ttm_cached;
|
||||
uint32_t extra_pages = params->extra_pages_num;
|
||||
u32 extra_pages = params->extra_pages_num;
|
||||
int num_pages = params->size >> PAGE_SHIFT;
|
||||
int err;
|
||||
|
||||
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt);
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, params->size);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, params->size, NULL);
|
||||
|
||||
err = ttm_tt_init(tt, bo, page_flags, caching, extra_pages);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
@ -82,14 +69,14 @@ static void ttm_tt_init_misaligned(struct kunit *test)
|
||||
struct ttm_buffer_object *bo;
|
||||
struct ttm_tt *tt;
|
||||
enum ttm_caching caching = ttm_cached;
|
||||
uint32_t size = SZ_8K;
|
||||
u32 size = SZ_8K;
|
||||
int num_pages = (size + SZ_4K) >> PAGE_SHIFT;
|
||||
int err;
|
||||
|
||||
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt);
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, size);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, size, NULL);
|
||||
|
||||
/* Make the object size misaligned */
|
||||
bo->base.size += 1;
|
||||
@ -110,7 +97,7 @@ static void ttm_tt_fini_basic(struct kunit *test)
|
||||
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt);
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
err = ttm_tt_init(tt, bo, 0, caching, 0);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
@ -130,7 +117,7 @@ static void ttm_tt_fini_sg(struct kunit *test)
|
||||
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt);
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
err = ttm_sg_tt_init(tt, bo, 0, caching);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
@ -151,7 +138,7 @@ static void ttm_tt_fini_shmem(struct kunit *test)
|
||||
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt);
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
err = ttm_tt_init(tt, bo, 0, caching, 0);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
@ -168,7 +155,7 @@ static void ttm_tt_create_basic(struct kunit *test)
|
||||
struct ttm_buffer_object *bo;
|
||||
int err;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
bo->type = ttm_bo_type_device;
|
||||
|
||||
dma_resv_lock(bo->base.resv, NULL);
|
||||
@ -187,7 +174,7 @@ static void ttm_tt_create_invalid_bo_type(struct kunit *test)
|
||||
struct ttm_buffer_object *bo;
|
||||
int err;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
bo->type = ttm_bo_type_sg + 1;
|
||||
|
||||
dma_resv_lock(bo->base.resv, NULL);
|
||||
@ -208,7 +195,7 @@ static void ttm_tt_create_ttm_exists(struct kunit *test)
|
||||
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt);
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
err = ttm_tt_init(tt, bo, 0, caching, 0);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
@ -224,7 +211,7 @@ static void ttm_tt_create_ttm_exists(struct kunit *test)
|
||||
}
|
||||
|
||||
static struct ttm_tt *ttm_tt_null_create(struct ttm_buffer_object *bo,
|
||||
uint32_t page_flags)
|
||||
u32 page_flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@ -239,7 +226,7 @@ static void ttm_tt_create_failed(struct kunit *test)
|
||||
struct ttm_buffer_object *bo;
|
||||
int err;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
/* Update ttm_device_funcs so we don't alloc ttm_tt */
|
||||
devs->ttm_dev->funcs = &ttm_dev_empty_funcs;
|
||||
@ -257,7 +244,7 @@ static void ttm_tt_destroy_basic(struct kunit *test)
|
||||
struct ttm_buffer_object *bo;
|
||||
int err;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE);
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
dma_resv_lock(bo->base.resv, NULL);
|
||||
err = ttm_tt_create(bo, false);
|
||||
@ -269,6 +256,120 @@ static void ttm_tt_destroy_basic(struct kunit *test)
|
||||
ttm_tt_destroy(devs->ttm_dev, bo->ttm);
|
||||
}
|
||||
|
||||
static void ttm_tt_populate_null_ttm(struct kunit *test)
|
||||
{
|
||||
const struct ttm_test_devices *devs = test->priv;
|
||||
struct ttm_operation_ctx ctx = { };
|
||||
int err;
|
||||
|
||||
err = ttm_tt_populate(devs->ttm_dev, NULL, &ctx);
|
||||
KUNIT_ASSERT_EQ(test, err, -EINVAL);
|
||||
}
|
||||
|
||||
static void ttm_tt_populate_populated_ttm(struct kunit *test)
|
||||
{
|
||||
const struct ttm_test_devices *devs = test->priv;
|
||||
struct ttm_operation_ctx ctx = { };
|
||||
struct ttm_buffer_object *bo;
|
||||
struct ttm_tt *tt;
|
||||
struct page *populated_page;
|
||||
int err;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt);
|
||||
|
||||
err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
|
||||
err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
populated_page = *tt->pages;
|
||||
|
||||
err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
|
||||
KUNIT_ASSERT_PTR_EQ(test, populated_page, *tt->pages);
|
||||
}
|
||||
|
||||
static void ttm_tt_unpopulate_basic(struct kunit *test)
|
||||
{
|
||||
const struct ttm_test_devices *devs = test->priv;
|
||||
struct ttm_operation_ctx ctx = { };
|
||||
struct ttm_buffer_object *bo;
|
||||
struct ttm_tt *tt;
|
||||
int err;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt);
|
||||
|
||||
err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
|
||||
err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
KUNIT_ASSERT_TRUE(test, ttm_tt_is_populated(tt));
|
||||
|
||||
ttm_tt_unpopulate(devs->ttm_dev, tt);
|
||||
KUNIT_ASSERT_FALSE(test, ttm_tt_is_populated(tt));
|
||||
}
|
||||
|
||||
static void ttm_tt_unpopulate_empty_ttm(struct kunit *test)
|
||||
{
|
||||
const struct ttm_test_devices *devs = test->priv;
|
||||
struct ttm_buffer_object *bo;
|
||||
struct ttm_tt *tt;
|
||||
int err;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt);
|
||||
|
||||
err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
|
||||
ttm_tt_unpopulate(devs->ttm_dev, tt);
|
||||
/* Expect graceful handling of unpopulated TTs */
|
||||
}
|
||||
|
||||
static void ttm_tt_swapin_basic(struct kunit *test)
|
||||
{
|
||||
const struct ttm_test_devices *devs = test->priv;
|
||||
int expected_num_pages = BO_SIZE >> PAGE_SHIFT;
|
||||
struct ttm_operation_ctx ctx = { };
|
||||
struct ttm_buffer_object *bo;
|
||||
struct ttm_tt *tt;
|
||||
int err, num_pages;
|
||||
|
||||
bo = ttm_bo_kunit_init(test, test->priv, BO_SIZE, NULL);
|
||||
|
||||
tt = kunit_kzalloc(test, sizeof(*tt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt);
|
||||
|
||||
err = ttm_tt_init(tt, bo, 0, ttm_cached, 0);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
|
||||
err = ttm_tt_populate(devs->ttm_dev, tt, &ctx);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
KUNIT_ASSERT_TRUE(test, ttm_tt_is_populated(tt));
|
||||
|
||||
num_pages = ttm_tt_swapout(devs->ttm_dev, tt, GFP_KERNEL);
|
||||
KUNIT_ASSERT_EQ(test, num_pages, expected_num_pages);
|
||||
KUNIT_ASSERT_NOT_NULL(test, tt->swap_storage);
|
||||
KUNIT_ASSERT_TRUE(test, tt->page_flags & TTM_TT_FLAG_SWAPPED);
|
||||
|
||||
/* Swapout depopulates TT, allocate pages and then swap them in */
|
||||
err = ttm_pool_alloc(&devs->ttm_dev->pool, tt, &ctx);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
|
||||
err = ttm_tt_swapin(tt);
|
||||
KUNIT_ASSERT_EQ(test, err, 0);
|
||||
KUNIT_ASSERT_NULL(test, tt->swap_storage);
|
||||
KUNIT_ASSERT_FALSE(test, tt->page_flags & TTM_TT_FLAG_SWAPPED);
|
||||
}
|
||||
|
||||
static struct kunit_case ttm_tt_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(ttm_tt_init_basic, ttm_tt_init_basic_gen_params),
|
||||
KUNIT_CASE(ttm_tt_init_misaligned),
|
||||
@ -280,16 +381,22 @@ static struct kunit_case ttm_tt_test_cases[] = {
|
||||
KUNIT_CASE(ttm_tt_create_ttm_exists),
|
||||
KUNIT_CASE(ttm_tt_create_failed),
|
||||
KUNIT_CASE(ttm_tt_destroy_basic),
|
||||
KUNIT_CASE(ttm_tt_populate_null_ttm),
|
||||
KUNIT_CASE(ttm_tt_populate_populated_ttm),
|
||||
KUNIT_CASE(ttm_tt_unpopulate_basic),
|
||||
KUNIT_CASE(ttm_tt_unpopulate_empty_ttm),
|
||||
KUNIT_CASE(ttm_tt_swapin_basic),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite ttm_tt_test_suite = {
|
||||
.name = "ttm_tt",
|
||||
.init = ttm_tt_test_init,
|
||||
.init = ttm_test_devices_all_init,
|
||||
.exit = ttm_test_devices_fini,
|
||||
.test_cases = ttm_tt_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suites(&ttm_tt_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("KUnit tests for ttm_tt APIs");
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
@ -251,6 +251,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
|
||||
out_err:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_swapin);
|
||||
|
||||
/**
|
||||
* ttm_tt_swapout - swap out tt object
|
||||
@ -308,6 +309,7 @@ int ttm_tt_swapout(struct ttm_device *bdev, struct ttm_tt *ttm,
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_swapout);
|
||||
|
||||
int ttm_tt_populate(struct ttm_device *bdev,
|
||||
struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
|
||||
@ -386,6 +388,7 @@ void ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm)
|
||||
|
||||
ttm->page_flags &= ~TTM_TT_FLAG_PRIV_POPULATED;
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_unpopulate);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
|
@ -234,6 +234,7 @@ enum vc4_vec_tv_mode_id {
|
||||
VC4_VEC_TV_MODE_PAL_60,
|
||||
VC4_VEC_TV_MODE_PAL_N,
|
||||
VC4_VEC_TV_MODE_SECAM,
|
||||
VC4_VEC_TV_MODE_MONOCHROME,
|
||||
};
|
||||
|
||||
struct vc4_vec_tv_mode {
|
||||
@ -324,6 +325,22 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
|
||||
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
|
||||
.custom_freq = 0x29c71c72,
|
||||
},
|
||||
{
|
||||
/* 50Hz mono */
|
||||
.mode = DRM_MODE_TV_MODE_MONOCHROME,
|
||||
.expected_htotal = 864,
|
||||
.config0 = VEC_CONFIG0_PAL_BDGHI_STD | VEC_CONFIG0_BURDIS |
|
||||
VEC_CONFIG0_CHRDIS,
|
||||
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
|
||||
},
|
||||
{
|
||||
/* 60Hz mono */
|
||||
.mode = DRM_MODE_TV_MODE_MONOCHROME,
|
||||
.expected_htotal = 858,
|
||||
.config0 = VEC_CONFIG0_PAL_M_STD | VEC_CONFIG0_BURDIS |
|
||||
VEC_CONFIG0_CHRDIS,
|
||||
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
|
||||
},
|
||||
};
|
||||
|
||||
static inline const struct vc4_vec_tv_mode *
|
||||
@ -351,6 +368,7 @@ static const struct drm_prop_enum_list legacy_tv_mode_names[] = {
|
||||
{ VC4_VEC_TV_MODE_PAL_M, "PAL-M", },
|
||||
{ VC4_VEC_TV_MODE_PAL_N, "PAL-N", },
|
||||
{ VC4_VEC_TV_MODE_SECAM, "SECAM", },
|
||||
{ VC4_VEC_TV_MODE_MONOCHROME, "Mono", },
|
||||
};
|
||||
|
||||
static enum drm_connector_status
|
||||
@ -406,6 +424,10 @@ vc4_vec_connector_set_property(struct drm_connector *connector,
|
||||
state->tv.mode = DRM_MODE_TV_MODE_SECAM;
|
||||
break;
|
||||
|
||||
case VC4_VEC_TV_MODE_MONOCHROME:
|
||||
state->tv.mode = DRM_MODE_TV_MODE_MONOCHROME;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -453,6 +475,10 @@ vc4_vec_connector_get_property(struct drm_connector *connector,
|
||||
*val = VC4_VEC_TV_MODE_SECAM;
|
||||
break;
|
||||
|
||||
case DRM_MODE_TV_MODE_MONOCHROME:
|
||||
*val = VC4_VEC_TV_MODE_MONOCHROME;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -503,6 +529,8 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
|
||||
|
||||
drm_object_attach_property(&connector->base, prop, VC4_VEC_TV_MODE_NTSC);
|
||||
|
||||
drm_connector_attach_tv_margin_properties(connector);
|
||||
|
||||
drm_connector_attach_encoder(connector, &vec->encoder.base);
|
||||
|
||||
return 0;
|
||||
@ -754,7 +782,8 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
|
||||
BIT(DRM_MODE_TV_MODE_PAL) |
|
||||
BIT(DRM_MODE_TV_MODE_PAL_M) |
|
||||
BIT(DRM_MODE_TV_MODE_PAL_N) |
|
||||
BIT(DRM_MODE_TV_MODE_SECAM));
|
||||
BIT(DRM_MODE_TV_MODE_SECAM) |
|
||||
BIT(DRM_MODE_TV_MODE_MONOCHROME));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/genalloc.h>
|
||||
#include <linux/module.h>
|
||||
@ -96,9 +97,16 @@ struct ipu_pre {
|
||||
|
||||
dma_addr_t buffer_paddr;
|
||||
void *buffer_virt;
|
||||
bool in_use;
|
||||
unsigned int safe_window_end;
|
||||
unsigned int last_bufaddr;
|
||||
|
||||
struct {
|
||||
bool in_use;
|
||||
uint64_t modifier;
|
||||
unsigned int height;
|
||||
unsigned int safe_window_end;
|
||||
unsigned int bufaddr;
|
||||
u32 ctrl;
|
||||
u8 cpp;
|
||||
} cur;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(ipu_pre_list_mutex);
|
||||
@ -113,8 +121,8 @@ int ipu_pre_get_available_count(void)
|
||||
struct ipu_pre *
|
||||
ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
|
||||
{
|
||||
struct device_node *pre_node = of_parse_phandle(dev->of_node,
|
||||
name, index);
|
||||
struct device_node *pre_node __free(device_node) =
|
||||
of_parse_phandle(dev->of_node, name, index);
|
||||
struct ipu_pre *pre;
|
||||
|
||||
mutex_lock(&ipu_pre_list_mutex);
|
||||
@ -123,14 +131,11 @@ ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
|
||||
mutex_unlock(&ipu_pre_list_mutex);
|
||||
device_link_add(dev, pre->dev,
|
||||
DL_FLAG_AUTOREMOVE_CONSUMER);
|
||||
of_node_put(pre_node);
|
||||
return pre;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&ipu_pre_list_mutex);
|
||||
|
||||
of_node_put(pre_node);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -138,7 +143,7 @@ int ipu_pre_get(struct ipu_pre *pre)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (pre->in_use)
|
||||
if (pre->cur.in_use)
|
||||
return -EBUSY;
|
||||
|
||||
/* first get the engine out of reset and remove clock gating */
|
||||
@ -151,7 +156,7 @@ int ipu_pre_get(struct ipu_pre *pre)
|
||||
IPU_PRE_CTRL_SDW_UPDATE;
|
||||
writel(val, pre->regs + IPU_PRE_CTRL);
|
||||
|
||||
pre->in_use = true;
|
||||
pre->cur.in_use = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -159,7 +164,41 @@ void ipu_pre_put(struct ipu_pre *pre)
|
||||
{
|
||||
writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
|
||||
|
||||
pre->in_use = false;
|
||||
pre->cur.in_use = false;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ipu_pre_update_safe_window(struct ipu_pre *pre)
|
||||
{
|
||||
if (pre->cur.modifier == DRM_FORMAT_MOD_LINEAR)
|
||||
pre->cur.safe_window_end = pre->cur.height - 2;
|
||||
else
|
||||
pre->cur.safe_window_end = DIV_ROUND_UP(pre->cur.height, 4) - 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ipu_pre_configure_modifier(struct ipu_pre *pre, uint64_t modifier)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(pre->regs + IPU_PRE_TPR_CTRL);
|
||||
val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK;
|
||||
if (modifier != DRM_FORMAT_MOD_LINEAR) {
|
||||
/* only support single buffer formats for now */
|
||||
val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF;
|
||||
if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)
|
||||
val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED;
|
||||
if (pre->cur.cpp == 2)
|
||||
val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT;
|
||||
}
|
||||
writel(val, pre->regs + IPU_PRE_TPR_CTRL);
|
||||
|
||||
if (modifier == DRM_FORMAT_MOD_LINEAR)
|
||||
pre->cur.ctrl &= ~IPU_PRE_CTRL_BLOCK_EN;
|
||||
else
|
||||
pre->cur.ctrl |= IPU_PRE_CTRL_BLOCK_EN;
|
||||
|
||||
pre->cur.modifier = modifier;
|
||||
}
|
||||
|
||||
void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
|
||||
@ -170,15 +209,16 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
|
||||
u32 active_bpp = info->cpp[0] >> 1;
|
||||
u32 val;
|
||||
|
||||
pre->cur.bufaddr = bufaddr;
|
||||
pre->cur.height = height;
|
||||
pre->cur.cpp = info->cpp[0];
|
||||
pre->cur.ctrl = readl(pre->regs + IPU_PRE_CTRL);
|
||||
|
||||
/* calculate safe window for ctrl register updates */
|
||||
if (modifier == DRM_FORMAT_MOD_LINEAR)
|
||||
pre->safe_window_end = height - 2;
|
||||
else
|
||||
pre->safe_window_end = DIV_ROUND_UP(height, 4) - 1;
|
||||
ipu_pre_update_safe_window(pre);
|
||||
|
||||
writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
|
||||
writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
|
||||
pre->last_bufaddr = bufaddr;
|
||||
|
||||
val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
|
||||
IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
|
||||
@ -208,42 +248,30 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
|
||||
|
||||
writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR);
|
||||
|
||||
val = readl(pre->regs + IPU_PRE_TPR_CTRL);
|
||||
val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK;
|
||||
if (modifier != DRM_FORMAT_MOD_LINEAR) {
|
||||
/* only support single buffer formats for now */
|
||||
val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF;
|
||||
if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)
|
||||
val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED;
|
||||
if (info->cpp[0] == 2)
|
||||
val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT;
|
||||
}
|
||||
writel(val, pre->regs + IPU_PRE_TPR_CTRL);
|
||||
ipu_pre_configure_modifier(pre, modifier);
|
||||
|
||||
val = readl(pre->regs + IPU_PRE_CTRL);
|
||||
val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE |
|
||||
IPU_PRE_CTRL_SDW_UPDATE;
|
||||
if (modifier == DRM_FORMAT_MOD_LINEAR)
|
||||
val &= ~IPU_PRE_CTRL_BLOCK_EN;
|
||||
else
|
||||
val |= IPU_PRE_CTRL_BLOCK_EN;
|
||||
writel(val, pre->regs + IPU_PRE_CTRL);
|
||||
pre->cur.ctrl |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE;
|
||||
writel(pre->cur.ctrl | IPU_PRE_CTRL_SDW_UPDATE,
|
||||
pre->regs + IPU_PRE_CTRL);
|
||||
}
|
||||
|
||||
void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
|
||||
void ipu_pre_update(struct ipu_pre *pre, uint64_t modifier, unsigned int bufaddr)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(5);
|
||||
unsigned short current_yblock;
|
||||
u32 val;
|
||||
|
||||
if (bufaddr == pre->last_bufaddr)
|
||||
if (bufaddr == pre->cur.bufaddr &&
|
||||
modifier == pre->cur.modifier)
|
||||
return;
|
||||
|
||||
writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
|
||||
pre->last_bufaddr = bufaddr;
|
||||
pre->cur.bufaddr = bufaddr;
|
||||
|
||||
do {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
if (modifier != pre->cur.modifier)
|
||||
ipu_pre_configure_modifier(pre, modifier);
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
unsigned short current_yblock;
|
||||
u32 val;
|
||||
|
||||
if (i > 500) {
|
||||
dev_warn(pre->dev, "timeout waiting for PRE safe window\n");
|
||||
return;
|
||||
}
|
||||
@ -252,9 +280,20 @@ void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
|
||||
current_yblock =
|
||||
(val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) &
|
||||
IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK;
|
||||
} while (current_yblock == 0 || current_yblock >= pre->safe_window_end);
|
||||
|
||||
writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
|
||||
if (current_yblock != 0 &&
|
||||
current_yblock < pre->cur.safe_window_end)
|
||||
break;
|
||||
|
||||
udelay(10);
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
writel(pre->cur.ctrl | IPU_PRE_CTRL_SDW_UPDATE,
|
||||
pre->regs + IPU_PRE_CTRL);
|
||||
|
||||
/* calculate safe window for the next update with the new modifier */
|
||||
ipu_pre_update_safe_window(pre);
|
||||
}
|
||||
|
||||
bool ipu_pre_update_pending(struct ipu_pre *pre)
|
||||
|
@ -287,7 +287,7 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
|
||||
chan = &prg->chan[prg_chan];
|
||||
|
||||
if (chan->enabled) {
|
||||
ipu_pre_update(prg->pres[chan->used_pre], *eba);
|
||||
ipu_pre_update(prg->pres[chan->used_pre], modifier, *eba);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -263,7 +263,7 @@ u32 ipu_pre_get_baddr(struct ipu_pre *pre);
|
||||
void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
|
||||
unsigned int height, unsigned int stride, u32 format,
|
||||
uint64_t modifier, unsigned int bufaddr);
|
||||
void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
|
||||
void ipu_pre_update(struct ipu_pre *pre, uint64_t modifier, unsigned int bufaddr);
|
||||
bool ipu_pre_update_pending(struct ipu_pre *pre);
|
||||
|
||||
struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
|
||||
|
@ -8,6 +8,8 @@ menuconfig LOGO
|
||||
depends on FB_CORE || SGI_NEWPORT_CONSOLE
|
||||
help
|
||||
Enable and select frame buffer bootup logos.
|
||||
Monochrome logos will also be used by the DRM panic handler, if
|
||||
enabled.
|
||||
|
||||
if LOGO
|
||||
|
||||
|
@ -29,8 +29,7 @@ struct analogix_dp_plat_data {
|
||||
struct drm_connector *connector;
|
||||
bool skip_connector;
|
||||
|
||||
int (*power_on_start)(struct analogix_dp_plat_data *);
|
||||
int (*power_on_end)(struct analogix_dp_plat_data *);
|
||||
int (*power_on)(struct analogix_dp_plat_data *);
|
||||
int (*power_off)(struct analogix_dp_plat_data *);
|
||||
int (*attach)(struct analogix_dp_plat_data *, struct drm_bridge *,
|
||||
struct drm_connector *);
|
||||
@ -45,7 +44,6 @@ struct analogix_dp_device *
|
||||
analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data);
|
||||
int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev);
|
||||
void analogix_dp_unbind(struct analogix_dp_device *dp);
|
||||
void analogix_dp_remove(struct analogix_dp_device *dp);
|
||||
|
||||
int analogix_dp_start_crc(struct drm_connector *connector);
|
||||
int analogix_dp_stop_crc(struct drm_connector *connector);
|
||||
|
@ -16,7 +16,7 @@ int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
|
||||
|
||||
int drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *connector,
|
||||
struct hdmi_audio_infoframe *frame);
|
||||
int drm_atomic_helper_connector_hdmi_disable_audio_infoframe(struct drm_connector *connector);
|
||||
int drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *connector);
|
||||
int drm_atomic_helper_connector_hdmi_update_infoframes(struct drm_connector *connector,
|
||||
struct drm_atomic_state *state);
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define __DRM_MIPI_DSI_H__
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
struct mipi_dsi_host;
|
||||
struct mipi_dsi_device;
|
||||
@ -297,6 +298,12 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
|
||||
msleep(delay); \
|
||||
} while (0)
|
||||
|
||||
#define mipi_dsi_usleep_range(ctx, min, max) \
|
||||
do { \
|
||||
if (!(ctx)->accum_err) \
|
||||
usleep_range(min, max); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
|
||||
* @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking
|
||||
|
@ -39,7 +39,11 @@
|
||||
#include "ttm_device.h"
|
||||
|
||||
/* Default number of pre-faulted pages in the TTM fault handler */
|
||||
#if CONFIG_PGTABLE_LEVELS > 2
|
||||
#define TTM_BO_VM_NUM_PREFAULT (1 << (PMD_SHIFT - PAGE_SHIFT))
|
||||
#else
|
||||
#define TTM_BO_VM_NUM_PREFAULT 16
|
||||
#endif
|
||||
|
||||
struct iosys_map;
|
||||
|
||||
|
@ -105,7 +105,8 @@ config FONT_SUN8x16
|
||||
|
||||
config FONT_SUN12x22
|
||||
bool "Sparc console 12x22 font (not supported by all drivers)"
|
||||
depends on (FRAMEBUFFER_CONSOLE && (!SPARC && FONTS || SPARC)) || DRM_PANIC
|
||||
depends on FRAMEBUFFER_CONSOLE || DRM_PANIC
|
||||
depends on !SPARC && FONTS
|
||||
help
|
||||
This is the high resolution console font for Sun machines with very
|
||||
big letters (like the letters used in the SPARC PROM). If the
|
||||
@ -113,7 +114,8 @@ config FONT_SUN12x22
|
||||
|
||||
config FONT_TER16x32
|
||||
bool "Terminus 16x32 font (not supported by all drivers)"
|
||||
depends on (FRAMEBUFFER_CONSOLE && (!SPARC && FONTS || SPARC)) || DRM_PANIC
|
||||
depends on FRAMEBUFFER_CONSOLE || DRM_PANIC
|
||||
depends on !SPARC && FONTS || SPARC
|
||||
help
|
||||
Terminus Font is a clean, fixed width bitmap font, designed
|
||||
for long (8 and more hours per day) work with computers.
|
||||
|
Loading…
Reference in New Issue
Block a user