mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
drm-misc-next for v6.12:
Cross-subsystem Changes: string: - add mem_is_zero() Core Changes: edid: - use mem_is_zero() Driver Changes: ast: - reorganize output code by type (VGA, DP, etc) - convert to struct drm_edid - fix BMC handling for all outputs bridge: - anx7625: simplify OF array handling - dw-hdmi: simplify clock handling - lontium-lt8912b: fix mode validation - nwl-dsi: fix mode vsync/hsync polarity panel: - ili9341: fix comments - jd9365da: fix "exit sleep" commands - jdi-fhd-r63452: simplify error handling with DSI multi-style helpers - mantix-mlaf057we51: simplify error handling with DSI multi-style helpers - simple: support Innolux G070ACE-LH3 plus DT bindings; support On Tat Industrial Company KD50G21-40NT-A1 plus DT bindings - st7701: decouple DSI and DRM code; add SPI support; support Anbernic RG28XX plus DT bindings vc4: - fix PM during detect - replace DRM_ERROR() with drm_error() - v3d: simplify clock retrieval -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEchf7rIzpz2NEoWjlaA3BHVMLeiMFAmbHUycACgkQaA3BHVML eiM5fAgAg3tFTVNhCXnam+9O619aG9nFFq1m4+ym/bKO5vrrOqua4V+Dz5vZWmH3 L1lw1hrpHurpNwpCtE3FCmhZrHote2p91R/q3sKp+Pv6rLlcVqLIy0rUDJFHzgjm p4Pc9JTTJMG4DoigzKzKVTE1d4cLGDLWxxpaMDqp81lGztFKmxipvVDyA3etQ1E0 xozitabuT4mffCf0kFj4wUwpfIha1WN2MEfRB2CvTSF/ha/y6lyKY9L+Hs/3pDE1 nsbz5BJMOvjE5TjqheAux/DknxU/NLEy3E6X4eOZ+B94NusYOj9cVmt6FUUEnvwB 0W/QvXd7IVXODkeAQKq1lOI5wmMgoA== =sIJI -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2024-08-22' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next drm-misc-next for v6.12: Cross-subsystem Changes: string: - add mem_is_zero() Core Changes: edid: - use mem_is_zero() Driver Changes: ast: - reorganize output code by type (VGA, DP, etc) - convert to struct drm_edid - fix BMC handling for all outputs bridge: - anx7625: simplify OF array handling - dw-hdmi: simplify clock handling - lontium-lt8912b: fix mode validation - nwl-dsi: fix mode vsync/hsync polarity panel: - ili9341: fix comments - jd9365da: fix "exit sleep" commands - jdi-fhd-r63452: simplify error handling with DSI multi-style helpers - mantix-mlaf057we51: simplify error handling with DSI multi-style helpers - simple: support Innolux G070ACE-LH3 plus DT bindings; support On Tat Industrial Company KD50G21-40NT-A1 plus DT bindings - st7701: decouple DSI and DRM code; add SPI support; support Anbernic RG28XX plus DT bindings vc4: - fix PM during detect - replace DRM_ERROR() with drm_error() - v3d: simplify clock retrieval Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20240822150710.GA243952@localhost.localdomain
This commit is contained in:
commit
f9ae00b1cf
@ -158,6 +158,8 @@ properties:
|
||||
- innolux,at070tn92
|
||||
# Innolux G070ACE-L01 7" WVGA (800x480) TFT LCD panel
|
||||
- innolux,g070ace-l01
|
||||
# Innolux G070ACE-LH3 7" WVGA (800x480) TFT LCD panel with WLED backlight
|
||||
- innolux,g070ace-lh3
|
||||
# Innolux G070Y2-L01 7" WVGA (800x480) TFT LCD panel
|
||||
- innolux,g070y2-l01
|
||||
# Innolux G070Y2-T02 7" WVGA (800x480) TFT LCD TTL panel
|
||||
@ -222,6 +224,8 @@ properties:
|
||||
- okaya,rs800480t-7x0gp
|
||||
# Olimex 4.3" TFT LCD panel
|
||||
- olimex,lcd-olinuxino-43-ts
|
||||
# On Tat Industrial Company 5" DPI TFT panel.
|
||||
- ontat,kd50g21-40nt-a1
|
||||
# On Tat Industrial Company 7" DPI TFT panel.
|
||||
- ontat,yx700wv03
|
||||
# OrtusTech COM37H3M05DTC Blanview 3.7" VGA portrait TFT-LCD panel
|
||||
|
@ -20,21 +20,19 @@ description: |
|
||||
Densitron DMT028VGHMCMI-1A is 480x640, 2-lane MIPI DSI LCD panel
|
||||
which has built-in ST7701 chip.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- anbernic,rg-arc-panel
|
||||
- anbernic,rg28xx-panel
|
||||
- densitron,dmt028vghmcmi-1a
|
||||
- elida,kd50t048a
|
||||
- techstar,ts8550b
|
||||
- const: sitronix,st7701
|
||||
|
||||
reg:
|
||||
description: DSI virtual channel used by that screen
|
||||
description: DSI / SPI channel used by that screen
|
||||
maxItems: 1
|
||||
|
||||
VCC-supply:
|
||||
@ -43,6 +41,13 @@ properties:
|
||||
IOVCC-supply:
|
||||
description: I/O system regulator
|
||||
|
||||
dc-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
Controller data/command selection (D/CX) in 4-line SPI mode.
|
||||
If not set, the controller is in 3-line SPI mode.
|
||||
Disallowed for DSI.
|
||||
|
||||
port: true
|
||||
reset-gpios: true
|
||||
rotation: true
|
||||
@ -57,7 +62,38 @@ required:
|
||||
- port
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
# SPI connected panels
|
||||
enum:
|
||||
- anbernic,rg28xx-panel
|
||||
then:
|
||||
$ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
not:
|
||||
contains:
|
||||
# DSI or SPI without D/CX pin
|
||||
enum:
|
||||
- anbernic,rg-arc-panel
|
||||
- anbernic,rg28xx-panel
|
||||
- densitron,dmt028vghmcmi-1a
|
||||
- elida,kd50t048a
|
||||
- techstar,ts8550b
|
||||
then:
|
||||
required:
|
||||
- dc-gpios
|
||||
else:
|
||||
properties:
|
||||
dc-gpios: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
@ -82,3 +118,26 @@ examples:
|
||||
};
|
||||
};
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "anbernic,rg28xx-panel", "sitronix,st7701";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <3125000>;
|
||||
VCC-supply = <®_lcd>;
|
||||
IOVCC-supply = <®_lcd>;
|
||||
reset-gpios = <&pio 8 14 GPIO_ACTIVE_HIGH>; /* LCD-RST: PI14 */
|
||||
backlight = <&backlight>;
|
||||
|
||||
port {
|
||||
panel_in_rgb: endpoint {
|
||||
remote-endpoint = <&tcon_lcd0_out_lcd>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -18771,7 +18771,6 @@ F: include/dt-bindings/clock/qcom,*
|
||||
QUALCOMM CLOUD AI (QAIC) DRIVER
|
||||
M: Jeffrey Hugo <quic_jhugo@quicinc.com>
|
||||
R: Carl Vanderlip <quic_carlv@quicinc.com>
|
||||
R: Pranjal Ramajor Asha Kanojiya <quic_pkanojiy@quicinc.com>
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Supported
|
||||
|
@ -11,6 +11,8 @@ ast-y := \
|
||||
ast_main.o \
|
||||
ast_mm.o \
|
||||
ast_mode.o \
|
||||
ast_post.o
|
||||
ast_post.o \
|
||||
ast_sil164.o \
|
||||
ast_vga.o
|
||||
|
||||
obj-$(CONFIG_DRM_AST) := ast.o
|
||||
|
@ -4,32 +4,58 @@
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "ast_drv.h"
|
||||
|
||||
bool ast_astdp_is_connected(struct ast_device *ast)
|
||||
static bool ast_astdp_is_connected(struct ast_device *ast)
|
||||
{
|
||||
if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, AST_IO_VGACRDF_HPD))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
|
||||
static int ast_astdp_read_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
struct ast_device *ast = data;
|
||||
size_t rdlen = round_up(len, 4);
|
||||
int ret = 0;
|
||||
u8 i;
|
||||
unsigned int i;
|
||||
|
||||
if (block > 0)
|
||||
return -EIO; /* extension headers not supported */
|
||||
|
||||
/*
|
||||
* Protect access to I/O registers from concurrent modesetting
|
||||
* by acquiring the I/O-register lock.
|
||||
*/
|
||||
mutex_lock(&ast->modeset_lock);
|
||||
|
||||
/* Start reading EDID data */
|
||||
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xe5, (u8)~AST_IO_VGACRE5_EDID_READ_DONE, 0x00);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
for (i = 0; i < rdlen; i += 4) {
|
||||
unsigned int offset;
|
||||
unsigned int j;
|
||||
u8 ediddata[4];
|
||||
u8 vgacre4;
|
||||
|
||||
offset = (i + block * EDID_LENGTH) / 4;
|
||||
if (offset >= 64) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
vgacre4 = offset;
|
||||
|
||||
/*
|
||||
* CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
|
||||
*/
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xe4, i);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xe4, vgacre4);
|
||||
|
||||
/*
|
||||
* CRD7[b0]: valid flag for EDID
|
||||
@ -53,7 +79,7 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
|
||||
vgacrd7 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd7);
|
||||
if (vgacrd7 & AST_IO_VGACRD7_EDID_VALID_FLAG) {
|
||||
vgacrd6 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd6);
|
||||
if (vgacrd6 == i)
|
||||
if (vgacrd6 == offset)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -81,7 +107,8 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
|
||||
ediddata[2] = 0;
|
||||
}
|
||||
|
||||
ediddata += 4;
|
||||
memcpy(buf, ediddata, min((len - i), 4));
|
||||
buf += 4;
|
||||
}
|
||||
|
||||
out:
|
||||
@ -89,6 +116,8 @@ out:
|
||||
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xe5, (u8)~AST_IO_VGACRE5_EDID_READ_DONE,
|
||||
AST_IO_VGACRE5_EDID_READ_DONE);
|
||||
|
||||
mutex_unlock(&ast->modeset_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -120,7 +149,7 @@ int ast_dp_launch(struct ast_device *ast)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ast_dp_power_is_on(struct ast_device *ast)
|
||||
static bool ast_dp_power_is_on(struct ast_device *ast)
|
||||
{
|
||||
u8 vgacre3;
|
||||
|
||||
@ -129,7 +158,7 @@ bool ast_dp_power_is_on(struct ast_device *ast)
|
||||
return !(vgacre3 & AST_DP_PHY_SLEEP);
|
||||
}
|
||||
|
||||
void ast_dp_power_on_off(struct drm_device *dev, bool on)
|
||||
static void ast_dp_power_on_off(struct drm_device *dev, bool on)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
// Read and Turn off DP PHY sleep
|
||||
@ -141,9 +170,11 @@ void ast_dp_power_on_off(struct drm_device *dev, bool on)
|
||||
|
||||
// DP Power on/off
|
||||
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
|
||||
|
||||
msleep(50);
|
||||
}
|
||||
|
||||
void ast_dp_link_training(struct ast_device *ast)
|
||||
static void ast_dp_link_training(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
int i;
|
||||
@ -161,7 +192,7 @@ void ast_dp_link_training(struct ast_device *ast)
|
||||
drm_err(dev, "Link training failed\n");
|
||||
}
|
||||
|
||||
void ast_dp_set_on_off(struct drm_device *dev, bool on)
|
||||
static void ast_dp_set_on_off(struct drm_device *dev, bool on)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
u8 video_on_off = on;
|
||||
@ -180,7 +211,7 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on)
|
||||
}
|
||||
}
|
||||
|
||||
void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
|
||||
static void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(crtc->dev);
|
||||
|
||||
@ -253,3 +284,188 @@ void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mo
|
||||
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1);
|
||||
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx);
|
||||
}
|
||||
|
||||
static void ast_wait_for_vretrace(struct ast_device *ast)
|
||||
{
|
||||
unsigned long timeout = jiffies + HZ;
|
||||
u8 vgair1;
|
||||
|
||||
do {
|
||||
vgair1 = ast_io_read8(ast, AST_IO_VGAIR1_R);
|
||||
} while (!(vgair1 & AST_IO_VGAIR1_VREFRESH) && time_before(jiffies, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Encoder
|
||||
*/
|
||||
|
||||
static const struct drm_encoder_funcs ast_astdp_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
static void ast_astdp_encoder_helper_atomic_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_crtc *crtc = crtc_state->crtc;
|
||||
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
|
||||
struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
|
||||
|
||||
ast_dp_set_mode(crtc, vbios_mode_info);
|
||||
}
|
||||
|
||||
static void ast_astdp_encoder_helper_atomic_enable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
struct ast_connector *ast_connector = &ast->output.astdp.connector;
|
||||
|
||||
if (ast_connector->physical_status == connector_status_connected) {
|
||||
ast_dp_power_on_off(dev, AST_DP_POWER_ON);
|
||||
ast_dp_link_training(ast);
|
||||
|
||||
ast_wait_for_vretrace(ast);
|
||||
ast_dp_set_on_off(dev, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void ast_astdp_encoder_helper_atomic_disable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
|
||||
ast_dp_set_on_off(dev, 0);
|
||||
ast_dp_power_on_off(dev, AST_DP_POWER_OFF);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs ast_astdp_encoder_helper_funcs = {
|
||||
.atomic_mode_set = ast_astdp_encoder_helper_atomic_mode_set,
|
||||
.atomic_enable = ast_astdp_encoder_helper_atomic_enable,
|
||||
.atomic_disable = ast_astdp_encoder_helper_atomic_disable,
|
||||
};
|
||||
|
||||
/*
|
||||
* Connector
|
||||
*/
|
||||
|
||||
static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct ast_connector *ast_connector = to_ast_connector(connector);
|
||||
int count;
|
||||
|
||||
if (ast_connector->physical_status == connector_status_connected) {
|
||||
struct ast_device *ast = to_ast_device(connector->dev);
|
||||
const struct drm_edid *drm_edid;
|
||||
|
||||
drm_edid = drm_edid_read_custom(connector, ast_astdp_read_edid_block, ast);
|
||||
drm_edid_connector_update(connector, drm_edid);
|
||||
count = drm_edid_connector_add_modes(connector);
|
||||
drm_edid_free(drm_edid);
|
||||
} else {
|
||||
drm_edid_connector_update(connector, NULL);
|
||||
|
||||
/*
|
||||
* There's no EDID data without a connected monitor. Set BMC-
|
||||
* compatible modes in this case. The XGA default resolution
|
||||
* should work well for all BMCs.
|
||||
*/
|
||||
count = drm_add_modes_noedid(connector, 4096, 4096);
|
||||
if (count)
|
||||
drm_set_preferred_mode(connector, 1024, 768);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int ast_astdp_connector_helper_detect_ctx(struct drm_connector *connector,
|
||||
struct drm_modeset_acquire_ctx *ctx,
|
||||
bool force)
|
||||
{
|
||||
struct ast_connector *ast_connector = to_ast_connector(connector);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct ast_device *ast = to_ast_device(connector->dev);
|
||||
enum drm_connector_status status = connector_status_disconnected;
|
||||
bool power_is_on;
|
||||
|
||||
mutex_lock(&ast->modeset_lock);
|
||||
|
||||
power_is_on = ast_dp_power_is_on(ast);
|
||||
if (!power_is_on)
|
||||
ast_dp_power_on_off(dev, true);
|
||||
|
||||
if (ast_astdp_is_connected(ast))
|
||||
status = connector_status_connected;
|
||||
|
||||
if (!power_is_on && status == connector_status_disconnected)
|
||||
ast_dp_power_on_off(dev, false);
|
||||
|
||||
mutex_unlock(&ast->modeset_lock);
|
||||
|
||||
if (status != ast_connector->physical_status)
|
||||
++connector->epoch_counter;
|
||||
ast_connector->physical_status = status;
|
||||
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
|
||||
.get_modes = ast_astdp_connector_helper_get_modes,
|
||||
.detect_ctx = ast_astdp_connector_helper_detect_ctx,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs ast_astdp_connector_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector *connector)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = drm_connector_init(dev, connector, &ast_astdp_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DisplayPort);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_connector_helper_add(connector, &ast_astdp_connector_helper_funcs);
|
||||
|
||||
connector->interlace_allowed = 0;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_astdp_output_init(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_crtc *crtc = &ast->crtc;
|
||||
struct drm_encoder *encoder = &ast->output.astdp.encoder;
|
||||
struct ast_connector *ast_connector = &ast->output.astdp.connector;
|
||||
struct drm_connector *connector = &ast_connector->base;
|
||||
int ret;
|
||||
|
||||
ret = drm_encoder_init(dev, encoder, &ast_astdp_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
drm_encoder_helper_add(encoder, &ast_astdp_encoder_helper_funcs);
|
||||
|
||||
encoder->possible_crtcs = drm_crtc_mask(crtc);
|
||||
|
||||
ret = ast_astdp_connector_init(dev, connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
ast_connector->physical_status = connector->status;
|
||||
|
||||
ret = drm_connector_attach_encoder(connector, encoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -4,6 +4,11 @@
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "ast_drv.h"
|
||||
|
||||
MODULE_FIRMWARE("ast_dp501_fw.bin");
|
||||
@ -170,7 +175,7 @@ static void clear_cmd(struct ast_device *ast)
|
||||
}
|
||||
#endif
|
||||
|
||||
void ast_set_dp501_video_output(struct drm_device *dev, u8 mode)
|
||||
static void ast_set_dp501_video_output(struct drm_device *dev, u8 mode)
|
||||
{
|
||||
ast_write_cmd(dev, 0x40);
|
||||
ast_write_data(dev, mode);
|
||||
@ -272,7 +277,7 @@ static bool ast_launch_m68k(struct drm_device *dev)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_dp501_is_connected(struct ast_device *ast)
|
||||
static bool ast_dp501_is_connected(struct ast_device *ast)
|
||||
{
|
||||
u32 boot_address, offset, data;
|
||||
|
||||
@ -313,32 +318,30 @@ bool ast_dp501_is_connected(struct ast_device *ast)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
|
||||
static int ast_dp512_read_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
u32 i, boot_address, offset, data;
|
||||
u32 *pEDIDidx;
|
||||
struct ast_device *ast = data;
|
||||
size_t rdlen = round_up(len, 4);
|
||||
u32 i, boot_address, offset, ediddata;
|
||||
|
||||
if (!ast_dp501_is_connected(ast))
|
||||
return false;
|
||||
if (block > (512 / EDID_LENGTH))
|
||||
return -EIO;
|
||||
|
||||
offset = AST_DP501_EDID_DATA + block * EDID_LENGTH;
|
||||
|
||||
if (ast->config_mode == ast_use_p2a) {
|
||||
boot_address = get_fw_base(ast);
|
||||
|
||||
/* Read EDID */
|
||||
offset = AST_DP501_EDID_DATA;
|
||||
for (i = 0; i < 128; i += 4) {
|
||||
data = ast_mindwm(ast, boot_address + offset + i);
|
||||
pEDIDidx = (u32 *)(ediddata + i);
|
||||
*pEDIDidx = data;
|
||||
for (i = 0; i < rdlen; i += 4) {
|
||||
ediddata = ast_mindwm(ast, boot_address + offset + i);
|
||||
memcpy(buf, &ediddata, min((len - i), 4));
|
||||
buf += 4;
|
||||
}
|
||||
} else {
|
||||
/* Read EDID */
|
||||
offset = AST_DP501_EDID_DATA;
|
||||
for (i = 0; i < 128; i += 4) {
|
||||
data = readl(ast->dp501_fw_buf + offset + i);
|
||||
pEDIDidx = (u32 *)(ediddata + i);
|
||||
*pEDIDidx = data;
|
||||
for (i = 0; i < rdlen; i += 4) {
|
||||
ediddata = readl(ast->dp501_fw_buf + offset + i);
|
||||
memcpy(buf, &ediddata, min((len - i), 4));
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,3 +473,144 @@ void ast_init_3rdtx(struct drm_device *dev)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Encoder
|
||||
*/
|
||||
|
||||
static const struct drm_encoder_funcs ast_dp501_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
static void ast_dp501_encoder_helper_atomic_enable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
|
||||
ast_set_dp501_video_output(dev, 1);
|
||||
}
|
||||
|
||||
static void ast_dp501_encoder_helper_atomic_disable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
|
||||
ast_set_dp501_video_output(dev, 0);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs ast_dp501_encoder_helper_funcs = {
|
||||
.atomic_enable = ast_dp501_encoder_helper_atomic_enable,
|
||||
.atomic_disable = ast_dp501_encoder_helper_atomic_disable,
|
||||
};
|
||||
|
||||
/*
|
||||
* Connector
|
||||
*/
|
||||
|
||||
static int ast_dp501_connector_helper_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct ast_connector *ast_connector = to_ast_connector(connector);
|
||||
int count;
|
||||
|
||||
if (ast_connector->physical_status == connector_status_connected) {
|
||||
struct ast_device *ast = to_ast_device(connector->dev);
|
||||
const struct drm_edid *drm_edid;
|
||||
|
||||
drm_edid = drm_edid_read_custom(connector, ast_dp512_read_edid_block, ast);
|
||||
drm_edid_connector_update(connector, drm_edid);
|
||||
count = drm_edid_connector_add_modes(connector);
|
||||
drm_edid_free(drm_edid);
|
||||
} else {
|
||||
drm_edid_connector_update(connector, NULL);
|
||||
|
||||
/*
|
||||
* There's no EDID data without a connected monitor. Set BMC-
|
||||
* compatible modes in this case. The XGA default resolution
|
||||
* should work well for all BMCs.
|
||||
*/
|
||||
count = drm_add_modes_noedid(connector, 4096, 4096);
|
||||
if (count)
|
||||
drm_set_preferred_mode(connector, 1024, 768);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int ast_dp501_connector_helper_detect_ctx(struct drm_connector *connector,
|
||||
struct drm_modeset_acquire_ctx *ctx,
|
||||
bool force)
|
||||
{
|
||||
struct ast_connector *ast_connector = to_ast_connector(connector);
|
||||
struct ast_device *ast = to_ast_device(connector->dev);
|
||||
enum drm_connector_status status = connector_status_disconnected;
|
||||
|
||||
if (ast_dp501_is_connected(ast))
|
||||
status = connector_status_connected;
|
||||
|
||||
if (status != ast_connector->physical_status)
|
||||
++connector->epoch_counter;
|
||||
ast_connector->physical_status = status;
|
||||
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = {
|
||||
.get_modes = ast_dp501_connector_helper_get_modes,
|
||||
.detect_ctx = ast_dp501_connector_helper_detect_ctx,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs ast_dp501_connector_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector *connector)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = drm_connector_init(dev, connector, &ast_dp501_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DisplayPort);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_connector_helper_add(connector, &ast_dp501_connector_helper_funcs);
|
||||
|
||||
connector->interlace_allowed = 0;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_dp501_output_init(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_crtc *crtc = &ast->crtc;
|
||||
struct drm_encoder *encoder = &ast->output.dp501.encoder;
|
||||
struct ast_connector *ast_connector = &ast->output.dp501.connector;
|
||||
struct drm_connector *connector = &ast_connector->base;
|
||||
int ret;
|
||||
|
||||
ret = drm_encoder_init(dev, encoder, &ast_dp501_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
drm_encoder_helper_add(encoder, &ast_dp501_encoder_helper_funcs);
|
||||
|
||||
encoder->possible_crtcs = drm_crtc_mask(crtc);
|
||||
|
||||
ret = ast_dp501_connector_init(dev, connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
ast_connector->physical_status = connector->status;
|
||||
|
||||
ret = drm_connector_attach_encoder(connector, encoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -147,18 +147,19 @@ static inline struct ast_plane *to_ast_plane(struct drm_plane *plane)
|
||||
}
|
||||
|
||||
/*
|
||||
* BMC
|
||||
* Connector
|
||||
*/
|
||||
|
||||
struct ast_bmc_connector {
|
||||
struct ast_connector {
|
||||
struct drm_connector base;
|
||||
struct drm_connector *physical_connector;
|
||||
|
||||
enum drm_connector_status physical_status;
|
||||
};
|
||||
|
||||
static inline struct ast_bmc_connector *
|
||||
to_ast_bmc_connector(struct drm_connector *connector)
|
||||
static inline struct ast_connector *
|
||||
to_ast_connector(struct drm_connector *connector)
|
||||
{
|
||||
return container_of(connector, struct ast_bmc_connector, base);
|
||||
return container_of(connector, struct ast_connector, base);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -192,24 +193,20 @@ struct ast_device {
|
||||
struct {
|
||||
struct {
|
||||
struct drm_encoder encoder;
|
||||
struct drm_connector connector;
|
||||
struct ast_connector connector;
|
||||
} vga;
|
||||
struct {
|
||||
struct drm_encoder encoder;
|
||||
struct drm_connector connector;
|
||||
struct ast_connector connector;
|
||||
} sil164;
|
||||
struct {
|
||||
struct drm_encoder encoder;
|
||||
struct drm_connector connector;
|
||||
struct ast_connector connector;
|
||||
} dp501;
|
||||
struct {
|
||||
struct drm_encoder encoder;
|
||||
struct drm_connector connector;
|
||||
struct ast_connector connector;
|
||||
} astdp;
|
||||
struct {
|
||||
struct drm_encoder encoder;
|
||||
struct ast_bmc_connector bmc_connector;
|
||||
} bmc;
|
||||
} output;
|
||||
|
||||
bool support_wide_screen;
|
||||
@ -460,22 +457,17 @@ void ast_post_gpu(struct drm_device *dev);
|
||||
u32 ast_mindwm(struct ast_device *ast, u32 r);
|
||||
void ast_moutdwm(struct ast_device *ast, u32 r, u32 v);
|
||||
void ast_patch_ahb_2500(void __iomem *regs);
|
||||
|
||||
int ast_vga_output_init(struct ast_device *ast);
|
||||
int ast_sil164_output_init(struct ast_device *ast);
|
||||
|
||||
/* ast dp501 */
|
||||
void ast_set_dp501_video_output(struct drm_device *dev, u8 mode);
|
||||
bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);
|
||||
bool ast_dp501_is_connected(struct ast_device *ast);
|
||||
bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata);
|
||||
u8 ast_get_dp501_max_clk(struct drm_device *dev);
|
||||
void ast_init_3rdtx(struct drm_device *dev);
|
||||
int ast_dp501_output_init(struct ast_device *ast);
|
||||
|
||||
/* aspeed DP */
|
||||
bool ast_astdp_is_connected(struct ast_device *ast);
|
||||
int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata);
|
||||
int ast_dp_launch(struct ast_device *ast);
|
||||
bool ast_dp_power_is_on(struct ast_device *ast);
|
||||
void ast_dp_power_on_off(struct drm_device *dev, bool no);
|
||||
void ast_dp_link_training(struct ast_device *ast);
|
||||
void ast_dp_set_on_off(struct drm_device *dev, bool no);
|
||||
void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode);
|
||||
int ast_astdp_output_init(struct ast_device *ast);
|
||||
|
||||
#endif
|
||||
|
@ -34,10 +34,8 @@
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_format_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
@ -47,7 +45,6 @@
|
||||
#include <drm/drm_panic.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "ast_ddc.h"
|
||||
#include "ast_drv.h"
|
||||
#include "ast_tables.h"
|
||||
|
||||
@ -1310,573 +1307,6 @@ 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
|
||||
*/
|
||||
|
||||
static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs = {
|
||||
.get_modes = drm_connector_helper_get_modes,
|
||||
.detect_ctx = drm_connector_helper_detect_from_ddc,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs ast_vga_connector_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int ast_vga_connector_init(struct drm_device *dev, struct drm_connector *connector)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
struct i2c_adapter *ddc;
|
||||
int ret;
|
||||
|
||||
ddc = ast_ddc_create(ast);
|
||||
if (IS_ERR(ddc)) {
|
||||
ret = PTR_ERR(ddc);
|
||||
drm_err(dev, "failed to add DDC bus for connector; ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_connector_init_with_ddc(dev, connector, &ast_vga_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_VGA, ddc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_connector_helper_add(connector, &ast_vga_connector_helper_funcs);
|
||||
|
||||
connector->interlace_allowed = 0;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ast_vga_output_init(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_crtc *crtc = &ast->crtc;
|
||||
struct drm_encoder *encoder = &ast->output.vga.encoder;
|
||||
struct drm_connector *connector = &ast->output.vga.connector;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
|
||||
ret = ast_vga_connector_init(dev, connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_connector_attach_encoder(connector, encoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SIL164 Encoder
|
||||
*/
|
||||
|
||||
static const struct drm_encoder_funcs ast_sil164_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
/*
|
||||
* SIL164 Connector
|
||||
*/
|
||||
|
||||
static const struct drm_connector_helper_funcs ast_sil164_connector_helper_funcs = {
|
||||
.get_modes = drm_connector_helper_get_modes,
|
||||
.detect_ctx = drm_connector_helper_detect_from_ddc,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs ast_sil164_connector_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int ast_sil164_connector_init(struct drm_device *dev, struct drm_connector *connector)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
struct i2c_adapter *ddc;
|
||||
int ret;
|
||||
|
||||
ddc = ast_ddc_create(ast);
|
||||
if (IS_ERR(ddc)) {
|
||||
ret = PTR_ERR(ddc);
|
||||
drm_err(dev, "failed to add DDC bus for connector; ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_connector_init_with_ddc(dev, connector, &ast_sil164_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DVII, ddc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_connector_helper_add(connector, &ast_sil164_connector_helper_funcs);
|
||||
|
||||
connector->interlace_allowed = 0;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ast_sil164_output_init(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_crtc *crtc = &ast->crtc;
|
||||
struct drm_encoder *encoder = &ast->output.sil164.encoder;
|
||||
struct drm_connector *connector = &ast->output.sil164.connector;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
|
||||
ret = ast_sil164_connector_init(dev, connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_connector_attach_encoder(connector, encoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* DP501 Encoder
|
||||
*/
|
||||
|
||||
static const struct drm_encoder_funcs ast_dp501_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
static void ast_dp501_encoder_helper_atomic_enable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
|
||||
ast_set_dp501_video_output(dev, 1);
|
||||
}
|
||||
|
||||
static void ast_dp501_encoder_helper_atomic_disable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
|
||||
ast_set_dp501_video_output(dev, 0);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs ast_dp501_encoder_helper_funcs = {
|
||||
.atomic_enable = ast_dp501_encoder_helper_atomic_enable,
|
||||
.atomic_disable = ast_dp501_encoder_helper_atomic_disable,
|
||||
};
|
||||
|
||||
/*
|
||||
* DP501 Connector
|
||||
*/
|
||||
|
||||
static int ast_dp501_connector_helper_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
void *edid;
|
||||
bool succ;
|
||||
int count;
|
||||
|
||||
edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
|
||||
if (!edid)
|
||||
goto err_drm_connector_update_edid_property;
|
||||
|
||||
succ = ast_dp501_read_edid(connector->dev, edid);
|
||||
if (!succ)
|
||||
goto err_kfree;
|
||||
|
||||
drm_connector_update_edid_property(connector, edid);
|
||||
count = drm_add_edid_modes(connector, edid);
|
||||
kfree(edid);
|
||||
|
||||
return count;
|
||||
|
||||
err_kfree:
|
||||
kfree(edid);
|
||||
err_drm_connector_update_edid_property:
|
||||
drm_connector_update_edid_property(connector, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ast_dp501_connector_helper_detect_ctx(struct drm_connector *connector,
|
||||
struct drm_modeset_acquire_ctx *ctx,
|
||||
bool force)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(connector->dev);
|
||||
|
||||
if (ast_dp501_is_connected(ast))
|
||||
return connector_status_connected;
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = {
|
||||
.get_modes = ast_dp501_connector_helper_get_modes,
|
||||
.detect_ctx = ast_dp501_connector_helper_detect_ctx,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs ast_dp501_connector_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector *connector)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = drm_connector_init(dev, connector, &ast_dp501_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DisplayPort);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_connector_helper_add(connector, &ast_dp501_connector_helper_funcs);
|
||||
|
||||
connector->interlace_allowed = 0;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ast_dp501_output_init(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_crtc *crtc = &ast->crtc;
|
||||
struct drm_encoder *encoder = &ast->output.dp501.encoder;
|
||||
struct drm_connector *connector = &ast->output.dp501.connector;
|
||||
int ret;
|
||||
|
||||
ret = drm_encoder_init(dev, encoder, &ast_dp501_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
drm_encoder_helper_add(encoder, &ast_dp501_encoder_helper_funcs);
|
||||
|
||||
encoder->possible_crtcs = drm_crtc_mask(crtc);
|
||||
|
||||
ret = ast_dp501_connector_init(dev, connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_connector_attach_encoder(connector, encoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ASPEED Display-Port Encoder
|
||||
*/
|
||||
|
||||
static const struct drm_encoder_funcs ast_astdp_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
static void ast_astdp_encoder_helper_atomic_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_crtc *crtc = crtc_state->crtc;
|
||||
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
|
||||
struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
|
||||
|
||||
ast_dp_set_mode(crtc, vbios_mode_info);
|
||||
}
|
||||
|
||||
static void ast_astdp_encoder_helper_atomic_enable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
|
||||
ast_dp_power_on_off(dev, AST_DP_POWER_ON);
|
||||
ast_dp_link_training(ast);
|
||||
|
||||
ast_wait_for_vretrace(ast);
|
||||
ast_dp_set_on_off(dev, 1);
|
||||
}
|
||||
|
||||
static void ast_astdp_encoder_helper_atomic_disable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
|
||||
ast_dp_set_on_off(dev, 0);
|
||||
ast_dp_power_on_off(dev, AST_DP_POWER_OFF);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs ast_astdp_encoder_helper_funcs = {
|
||||
.atomic_mode_set = ast_astdp_encoder_helper_atomic_mode_set,
|
||||
.atomic_enable = ast_astdp_encoder_helper_atomic_enable,
|
||||
.atomic_disable = ast_astdp_encoder_helper_atomic_disable,
|
||||
};
|
||||
|
||||
/*
|
||||
* ASPEED Display-Port Connector
|
||||
*/
|
||||
|
||||
static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
void *edid;
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
|
||||
int succ;
|
||||
int count;
|
||||
|
||||
edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
|
||||
if (!edid)
|
||||
goto err_drm_connector_update_edid_property;
|
||||
|
||||
/*
|
||||
* Protect access to I/O registers from concurrent modesetting
|
||||
* by acquiring the I/O-register lock.
|
||||
*/
|
||||
mutex_lock(&ast->modeset_lock);
|
||||
|
||||
succ = ast_astdp_read_edid(connector->dev, edid);
|
||||
if (succ < 0)
|
||||
goto err_mutex_unlock;
|
||||
|
||||
mutex_unlock(&ast->modeset_lock);
|
||||
|
||||
drm_connector_update_edid_property(connector, edid);
|
||||
count = drm_add_edid_modes(connector, edid);
|
||||
kfree(edid);
|
||||
|
||||
return count;
|
||||
|
||||
err_mutex_unlock:
|
||||
mutex_unlock(&ast->modeset_lock);
|
||||
kfree(edid);
|
||||
err_drm_connector_update_edid_property:
|
||||
drm_connector_update_edid_property(connector, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ast_astdp_connector_helper_detect_ctx(struct drm_connector *connector,
|
||||
struct drm_modeset_acquire_ctx *ctx,
|
||||
bool force)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct ast_device *ast = to_ast_device(connector->dev);
|
||||
enum drm_connector_status status = connector_status_disconnected;
|
||||
struct drm_connector_state *connector_state = connector->state;
|
||||
bool is_active = false;
|
||||
|
||||
mutex_lock(&ast->modeset_lock);
|
||||
|
||||
if (connector_state && connector_state->crtc) {
|
||||
struct drm_crtc_state *crtc_state = connector_state->crtc->state;
|
||||
|
||||
if (crtc_state && crtc_state->active)
|
||||
is_active = true;
|
||||
}
|
||||
|
||||
if (!is_active && !ast_dp_power_is_on(ast)) {
|
||||
ast_dp_power_on_off(dev, true);
|
||||
msleep(50);
|
||||
}
|
||||
|
||||
if (ast_astdp_is_connected(ast))
|
||||
status = connector_status_connected;
|
||||
|
||||
if (!is_active && status == connector_status_disconnected)
|
||||
ast_dp_power_on_off(dev, false);
|
||||
|
||||
mutex_unlock(&ast->modeset_lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
|
||||
.get_modes = ast_astdp_connector_helper_get_modes,
|
||||
.detect_ctx = ast_astdp_connector_helper_detect_ctx,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs ast_astdp_connector_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector *connector)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = drm_connector_init(dev, connector, &ast_astdp_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DisplayPort);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_connector_helper_add(connector, &ast_astdp_connector_helper_funcs);
|
||||
|
||||
connector->interlace_allowed = 0;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ast_astdp_output_init(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_crtc *crtc = &ast->crtc;
|
||||
struct drm_encoder *encoder = &ast->output.astdp.encoder;
|
||||
struct drm_connector *connector = &ast->output.astdp.connector;
|
||||
int ret;
|
||||
|
||||
ret = drm_encoder_init(dev, encoder, &ast_astdp_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
drm_encoder_helper_add(encoder, &ast_astdp_encoder_helper_funcs);
|
||||
|
||||
encoder->possible_crtcs = drm_crtc_mask(crtc);
|
||||
|
||||
ret = ast_astdp_connector_init(dev, connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_connector_attach_encoder(connector, encoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMC virtual Connector
|
||||
*/
|
||||
|
||||
static const struct drm_encoder_funcs ast_bmc_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
static int ast_bmc_connector_helper_detect_ctx(struct drm_connector *connector,
|
||||
struct drm_modeset_acquire_ctx *ctx,
|
||||
bool force)
|
||||
{
|
||||
struct ast_bmc_connector *bmc_connector = to_ast_bmc_connector(connector);
|
||||
struct drm_connector *physical_connector = bmc_connector->physical_connector;
|
||||
|
||||
/*
|
||||
* Most user-space compositors cannot handle more than one connected
|
||||
* connector per CRTC. Hence, we only mark the BMC as connected if the
|
||||
* physical connector is disconnected. If the physical connector's status
|
||||
* is connected or unknown, the BMC remains disconnected. This has no
|
||||
* effect on the output of the BMC.
|
||||
*
|
||||
* FIXME: Remove this logic once user-space compositors can handle more
|
||||
* than one connector per CRTC. The BMC should always be connected.
|
||||
*/
|
||||
|
||||
if (physical_connector && physical_connector->status == connector_status_disconnected)
|
||||
return connector_status_connected;
|
||||
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
return drm_add_modes_noedid(connector, 4096, 4096);
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs ast_bmc_connector_helper_funcs = {
|
||||
.get_modes = ast_bmc_connector_helper_get_modes,
|
||||
.detect_ctx = ast_bmc_connector_helper_detect_ctx,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs ast_bmc_connector_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int ast_bmc_connector_init(struct drm_device *dev,
|
||||
struct ast_bmc_connector *bmc_connector,
|
||||
struct drm_connector *physical_connector)
|
||||
{
|
||||
struct drm_connector *connector = &bmc_connector->base;
|
||||
int ret;
|
||||
|
||||
ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_VIRTUAL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs);
|
||||
|
||||
bmc_connector->physical_connector = physical_connector;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ast_bmc_output_init(struct ast_device *ast,
|
||||
struct drm_connector *physical_connector)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_crtc *crtc = &ast->crtc;
|
||||
struct drm_encoder *encoder = &ast->output.bmc.encoder;
|
||||
struct ast_bmc_connector *bmc_connector = &ast->output.bmc.bmc_connector;
|
||||
struct drm_connector *connector = &bmc_connector->base;
|
||||
int ret;
|
||||
|
||||
ret = drm_encoder_init(dev, encoder,
|
||||
&ast_bmc_encoder_funcs,
|
||||
DRM_MODE_ENCODER_VIRTUAL, "ast_bmc");
|
||||
if (ret)
|
||||
return ret;
|
||||
encoder->possible_crtcs = drm_crtc_mask(crtc);
|
||||
|
||||
ret = ast_bmc_connector_init(dev, bmc_connector, physical_connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_connector_attach_encoder(connector, encoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mode config
|
||||
*/
|
||||
@ -1928,7 +1358,6 @@ static const struct drm_mode_config_funcs ast_mode_config_funcs = {
|
||||
int ast_mode_config_init(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_connector *physical_connector = NULL;
|
||||
int ret;
|
||||
|
||||
ret = drmm_mutex_init(dev, &ast->modeset_lock);
|
||||
@ -1973,29 +1402,22 @@ int ast_mode_config_init(struct ast_device *ast)
|
||||
ret = ast_vga_output_init(ast);
|
||||
if (ret)
|
||||
return ret;
|
||||
physical_connector = &ast->output.vga.connector;
|
||||
}
|
||||
if (ast->tx_chip_types & AST_TX_SIL164_BIT) {
|
||||
ret = ast_sil164_output_init(ast);
|
||||
if (ret)
|
||||
return ret;
|
||||
physical_connector = &ast->output.sil164.connector;
|
||||
}
|
||||
if (ast->tx_chip_types & AST_TX_DP501_BIT) {
|
||||
ret = ast_dp501_output_init(ast);
|
||||
if (ret)
|
||||
return ret;
|
||||
physical_connector = &ast->output.dp501.connector;
|
||||
}
|
||||
if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
|
||||
ret = ast_astdp_output_init(ast);
|
||||
if (ret)
|
||||
return ret;
|
||||
physical_connector = &ast->output.astdp.connector;
|
||||
}
|
||||
ret = ast_bmc_output_init(ast, physical_connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_mode_config_reset(dev);
|
||||
|
||||
|
127
drivers/gpu/drm/ast/ast_sil164.c
Normal file
127
drivers/gpu/drm/ast/ast_sil164.c
Normal file
@ -0,0 +1,127 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "ast_ddc.h"
|
||||
#include "ast_drv.h"
|
||||
|
||||
/*
|
||||
* Encoder
|
||||
*/
|
||||
|
||||
static const struct drm_encoder_funcs ast_sil164_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
/*
|
||||
* Connector
|
||||
*/
|
||||
|
||||
static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct ast_connector *ast_connector = to_ast_connector(connector);
|
||||
int count;
|
||||
|
||||
if (ast_connector->physical_status == connector_status_connected) {
|
||||
count = drm_connector_helper_get_modes(connector);
|
||||
} else {
|
||||
/*
|
||||
* There's no EDID data without a connected monitor. Set BMC-
|
||||
* compatible modes in this case. The XGA default resolution
|
||||
* should work well for all BMCs.
|
||||
*/
|
||||
count = drm_add_modes_noedid(connector, 4096, 4096);
|
||||
if (count)
|
||||
drm_set_preferred_mode(connector, 1024, 768);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int ast_sil164_connector_helper_detect_ctx(struct drm_connector *connector,
|
||||
struct drm_modeset_acquire_ctx *ctx,
|
||||
bool force)
|
||||
{
|
||||
struct ast_connector *ast_connector = to_ast_connector(connector);
|
||||
enum drm_connector_status status;
|
||||
|
||||
status = drm_connector_helper_detect_from_ddc(connector, ctx, force);
|
||||
|
||||
if (status != ast_connector->physical_status)
|
||||
++connector->epoch_counter;
|
||||
ast_connector->physical_status = status;
|
||||
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs ast_sil164_connector_helper_funcs = {
|
||||
.get_modes = ast_sil164_connector_helper_get_modes,
|
||||
.detect_ctx = ast_sil164_connector_helper_detect_ctx,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs ast_sil164_connector_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int ast_sil164_connector_init(struct drm_device *dev, struct drm_connector *connector)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
struct i2c_adapter *ddc;
|
||||
int ret;
|
||||
|
||||
ddc = ast_ddc_create(ast);
|
||||
if (IS_ERR(ddc)) {
|
||||
ret = PTR_ERR(ddc);
|
||||
drm_err(dev, "failed to add DDC bus for connector; ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_connector_init_with_ddc(dev, connector, &ast_sil164_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DVII, ddc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_connector_helper_add(connector, &ast_sil164_connector_helper_funcs);
|
||||
|
||||
connector->interlace_allowed = 0;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_sil164_output_init(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_crtc *crtc = &ast->crtc;
|
||||
struct drm_encoder *encoder = &ast->output.sil164.encoder;
|
||||
struct ast_connector *ast_connector = &ast->output.sil164.connector;
|
||||
struct drm_connector *connector = &ast_connector->base;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
|
||||
ret = ast_sil164_connector_init(dev, connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
ast_connector->physical_status = connector->status;
|
||||
|
||||
ret = drm_connector_attach_encoder(connector, encoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
127
drivers/gpu/drm/ast/ast_vga.c
Normal file
127
drivers/gpu/drm/ast/ast_vga.c
Normal file
@ -0,0 +1,127 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "ast_ddc.h"
|
||||
#include "ast_drv.h"
|
||||
|
||||
/*
|
||||
* Encoder
|
||||
*/
|
||||
|
||||
static const struct drm_encoder_funcs ast_vga_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
/*
|
||||
* Connector
|
||||
*/
|
||||
|
||||
static int ast_vga_connector_helper_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct ast_connector *ast_connector = to_ast_connector(connector);
|
||||
int count;
|
||||
|
||||
if (ast_connector->physical_status == connector_status_connected) {
|
||||
count = drm_connector_helper_get_modes(connector);
|
||||
} else {
|
||||
/*
|
||||
* There's no EDID data without a connected monitor. Set BMC-
|
||||
* compatible modes in this case. The XGA default resolution
|
||||
* should work well for all BMCs.
|
||||
*/
|
||||
count = drm_add_modes_noedid(connector, 4096, 4096);
|
||||
if (count)
|
||||
drm_set_preferred_mode(connector, 1024, 768);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int ast_vga_connector_helper_detect_ctx(struct drm_connector *connector,
|
||||
struct drm_modeset_acquire_ctx *ctx,
|
||||
bool force)
|
||||
{
|
||||
struct ast_connector *ast_connector = to_ast_connector(connector);
|
||||
enum drm_connector_status status;
|
||||
|
||||
status = drm_connector_helper_detect_from_ddc(connector, ctx, force);
|
||||
|
||||
if (status != ast_connector->physical_status)
|
||||
++connector->epoch_counter;
|
||||
ast_connector->physical_status = status;
|
||||
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs = {
|
||||
.get_modes = ast_vga_connector_helper_get_modes,
|
||||
.detect_ctx = ast_vga_connector_helper_detect_ctx,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs ast_vga_connector_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int ast_vga_connector_init(struct drm_device *dev, struct drm_connector *connector)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(dev);
|
||||
struct i2c_adapter *ddc;
|
||||
int ret;
|
||||
|
||||
ddc = ast_ddc_create(ast);
|
||||
if (IS_ERR(ddc)) {
|
||||
ret = PTR_ERR(ddc);
|
||||
drm_err(dev, "failed to add DDC bus for connector; ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_connector_init_with_ddc(dev, connector, &ast_vga_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_VGA, ddc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_connector_helper_add(connector, &ast_vga_connector_helper_funcs);
|
||||
|
||||
connector->interlace_allowed = 0;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_vga_output_init(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_crtc *crtc = &ast->crtc;
|
||||
struct drm_encoder *encoder = &ast->output.vga.encoder;
|
||||
struct ast_connector *ast_connector = &ast->output.vga.connector;
|
||||
struct drm_connector *connector = &ast_connector->base;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
|
||||
ret = ast_vga_connector_init(dev, connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
ast_connector->physical_status = connector->status;
|
||||
|
||||
ret = drm_connector_attach_encoder(connector, encoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1647,25 +1647,15 @@ static int anx7625_get_swing_setting(struct device *dev,
|
||||
{
|
||||
int num_regs;
|
||||
|
||||
if (of_get_property(dev->of_node,
|
||||
"analogix,lane0-swing", &num_regs)) {
|
||||
if (num_regs > DP_TX_SWING_REG_CNT)
|
||||
num_regs = DP_TX_SWING_REG_CNT;
|
||||
|
||||
num_regs = of_property_read_variable_u8_array(dev->of_node, "analogix,lane0-swing",
|
||||
pdata->lane0_reg_data, 1, DP_TX_SWING_REG_CNT);
|
||||
if (num_regs > 0)
|
||||
pdata->dp_lane0_swing_reg_cnt = num_regs;
|
||||
of_property_read_u8_array(dev->of_node, "analogix,lane0-swing",
|
||||
pdata->lane0_reg_data, num_regs);
|
||||
}
|
||||
|
||||
if (of_get_property(dev->of_node,
|
||||
"analogix,lane1-swing", &num_regs)) {
|
||||
if (num_regs > DP_TX_SWING_REG_CNT)
|
||||
num_regs = DP_TX_SWING_REG_CNT;
|
||||
|
||||
num_regs = of_property_read_variable_u8_array(dev->of_node, "analogix,lane1-swing",
|
||||
pdata->lane1_reg_data, 1, DP_TX_SWING_REG_CNT);
|
||||
if (num_regs > 0)
|
||||
pdata->dp_lane1_swing_reg_cnt = num_regs;
|
||||
of_property_read_u8_array(dev->of_node, "analogix,lane1-swing",
|
||||
pdata->lane1_reg_data, num_regs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -422,22 +422,6 @@ static const struct drm_connector_funcs lt8912_connector_funcs = {
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static enum drm_mode_status
|
||||
lt8912_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->clock > 150000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
if (mode->hdisplay > 1920)
|
||||
return MODE_BAD_HVALUE;
|
||||
|
||||
if (mode->vdisplay > 1080)
|
||||
return MODE_BAD_VVALUE;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static int lt8912_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
const struct drm_edid *drm_edid;
|
||||
@ -463,7 +447,6 @@ static int lt8912_connector_get_modes(struct drm_connector *connector)
|
||||
|
||||
static const struct drm_connector_helper_funcs lt8912_connector_helper_funcs = {
|
||||
.get_modes = lt8912_connector_get_modes,
|
||||
.mode_valid = lt8912_connector_mode_valid,
|
||||
};
|
||||
|
||||
static void lt8912_bridge_mode_set(struct drm_bridge *bridge,
|
||||
@ -605,6 +588,23 @@ static void lt8912_bridge_detach(struct drm_bridge *bridge)
|
||||
drm_bridge_hpd_disable(lt->hdmi_port);
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
lt8912_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
const struct drm_display_info *info,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->clock > 150000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
if (mode->hdisplay > 1920)
|
||||
return MODE_BAD_HVALUE;
|
||||
|
||||
if (mode->vdisplay > 1080)
|
||||
return MODE_BAD_VVALUE;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
lt8912_bridge_detect(struct drm_bridge *bridge)
|
||||
{
|
||||
@ -635,6 +635,7 @@ static const struct drm_edid *lt8912_bridge_edid_read(struct drm_bridge *bridge,
|
||||
static const struct drm_bridge_funcs lt8912_bridge_funcs = {
|
||||
.attach = lt8912_bridge_attach,
|
||||
.detach = lt8912_bridge_detach,
|
||||
.mode_valid = lt8912_bridge_mode_valid,
|
||||
.mode_set = lt8912_bridge_mode_set,
|
||||
.enable = lt8912_bridge_enable,
|
||||
.detect = lt8912_bridge_detect,
|
||||
|
@ -289,13 +289,13 @@ static int nwl_dsi_config_dpi(struct nwl_dsi *dsi)
|
||||
|
||||
nwl_dsi_write(dsi, NWL_DSI_INTERFACE_COLOR_CODING, NWL_DSI_DPI_24_BIT);
|
||||
nwl_dsi_write(dsi, NWL_DSI_PIXEL_FORMAT, color_format);
|
||||
/*
|
||||
* Adjusting input polarity based on the video mode results in
|
||||
* a black screen so always pick active low:
|
||||
*/
|
||||
nwl_dsi_write(dsi, NWL_DSI_VSYNC_POLARITY,
|
||||
dsi->mode.flags & DRM_MODE_FLAG_PVSYNC ?
|
||||
NWL_DSI_VSYNC_POLARITY_ACTIVE_HIGH :
|
||||
NWL_DSI_VSYNC_POLARITY_ACTIVE_LOW);
|
||||
nwl_dsi_write(dsi, NWL_DSI_HSYNC_POLARITY,
|
||||
dsi->mode.flags & DRM_MODE_FLAG_PHSYNC ?
|
||||
NWL_DSI_HSYNC_POLARITY_ACTIVE_HIGH :
|
||||
NWL_DSI_HSYNC_POLARITY_ACTIVE_LOW);
|
||||
|
||||
burst_mode = (dsi->dsi_mode_flags & MIPI_DSI_MODE_VIDEO_BURST) &&
|
||||
|
@ -30,11 +30,11 @@
|
||||
#define NWL_DSI_PIXEL_FORMAT 0x20c
|
||||
#define NWL_DSI_VSYNC_POLARITY 0x210
|
||||
#define NWL_DSI_VSYNC_POLARITY_ACTIVE_LOW 0
|
||||
#define NWL_DSI_VSYNC_POLARITY_ACTIVE_HIGH BIT(1)
|
||||
#define NWL_DSI_VSYNC_POLARITY_ACTIVE_HIGH BIT(0)
|
||||
|
||||
#define NWL_DSI_HSYNC_POLARITY 0x214
|
||||
#define NWL_DSI_HSYNC_POLARITY_ACTIVE_LOW 0
|
||||
#define NWL_DSI_HSYNC_POLARITY_ACTIVE_HIGH BIT(1)
|
||||
#define NWL_DSI_HSYNC_POLARITY_ACTIVE_HIGH BIT(0)
|
||||
|
||||
#define NWL_DSI_VIDEO_MODE 0x218
|
||||
#define NWL_DSI_HFP 0x21c
|
||||
|
@ -138,9 +138,6 @@ struct dw_hdmi {
|
||||
struct platform_device *audio;
|
||||
struct platform_device *cec;
|
||||
struct device *dev;
|
||||
struct clk *isfr_clk;
|
||||
struct clk *iahb_clk;
|
||||
struct clk *cec_clk;
|
||||
struct dw_hdmi_i2c *i2c;
|
||||
|
||||
struct hdmi_data_info hdmi_data;
|
||||
@ -3326,6 +3323,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
|
||||
struct device_node *ddc_node;
|
||||
struct dw_hdmi_cec_data cec;
|
||||
struct dw_hdmi *hdmi;
|
||||
struct clk *clk;
|
||||
struct resource *iores = NULL;
|
||||
int irq;
|
||||
int ret;
|
||||
@ -3405,50 +3403,27 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
|
||||
hdmi->regm = plat_data->regm;
|
||||
}
|
||||
|
||||
hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
|
||||
if (IS_ERR(hdmi->isfr_clk)) {
|
||||
ret = PTR_ERR(hdmi->isfr_clk);
|
||||
clk = devm_clk_get_enabled(hdmi->dev, "isfr");
|
||||
if (IS_ERR(clk)) {
|
||||
ret = PTR_ERR(clk);
|
||||
dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret);
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(hdmi->isfr_clk);
|
||||
if (ret) {
|
||||
dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret);
|
||||
clk = devm_clk_get_enabled(hdmi->dev, "iahb");
|
||||
if (IS_ERR(clk)) {
|
||||
ret = PTR_ERR(clk);
|
||||
dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret);
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb");
|
||||
if (IS_ERR(hdmi->iahb_clk)) {
|
||||
ret = PTR_ERR(hdmi->iahb_clk);
|
||||
dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret);
|
||||
goto err_isfr;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(hdmi->iahb_clk);
|
||||
if (ret) {
|
||||
dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret);
|
||||
goto err_isfr;
|
||||
}
|
||||
|
||||
hdmi->cec_clk = devm_clk_get(hdmi->dev, "cec");
|
||||
if (PTR_ERR(hdmi->cec_clk) == -ENOENT) {
|
||||
hdmi->cec_clk = NULL;
|
||||
} else if (IS_ERR(hdmi->cec_clk)) {
|
||||
ret = PTR_ERR(hdmi->cec_clk);
|
||||
clk = devm_clk_get_optional_enabled(hdmi->dev, "cec");
|
||||
if (IS_ERR(clk)) {
|
||||
ret = PTR_ERR(clk);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(hdmi->dev, "Cannot get HDMI cec clock: %d\n",
|
||||
ret);
|
||||
|
||||
hdmi->cec_clk = NULL;
|
||||
goto err_iahb;
|
||||
} else {
|
||||
ret = clk_prepare_enable(hdmi->cec_clk);
|
||||
if (ret) {
|
||||
dev_err(hdmi->dev, "Cannot enable HDMI cec clock: %d\n",
|
||||
ret);
|
||||
goto err_iahb;
|
||||
}
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
/* Product and revision IDs */
|
||||
@ -3462,12 +3437,12 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
|
||||
dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n",
|
||||
hdmi->version, prod_id0, prod_id1);
|
||||
ret = -ENODEV;
|
||||
goto err_iahb;
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
ret = dw_hdmi_detect_phy(hdmi);
|
||||
if (ret < 0)
|
||||
goto err_iahb;
|
||||
goto err_res;
|
||||
|
||||
dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP (%s)\n",
|
||||
hdmi->version >> 12, hdmi->version & 0xfff,
|
||||
@ -3479,14 +3454,14 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto err_iahb;
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
|
||||
dw_hdmi_irq, IRQF_SHARED,
|
||||
dev_name(dev), hdmi);
|
||||
if (ret)
|
||||
goto err_iahb;
|
||||
goto err_res;
|
||||
|
||||
/*
|
||||
* To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
|
||||
@ -3603,11 +3578,6 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
|
||||
|
||||
return hdmi;
|
||||
|
||||
err_iahb:
|
||||
clk_disable_unprepare(hdmi->iahb_clk);
|
||||
clk_disable_unprepare(hdmi->cec_clk);
|
||||
err_isfr:
|
||||
clk_disable_unprepare(hdmi->isfr_clk);
|
||||
err_res:
|
||||
i2c_put_adapter(hdmi->ddc);
|
||||
|
||||
@ -3627,10 +3597,6 @@ void dw_hdmi_remove(struct dw_hdmi *hdmi)
|
||||
/* Disable all interrupts */
|
||||
hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
|
||||
|
||||
clk_disable_unprepare(hdmi->iahb_clk);
|
||||
clk_disable_unprepare(hdmi->isfr_clk);
|
||||
clk_disable_unprepare(hdmi->cec_clk);
|
||||
|
||||
if (hdmi->i2c)
|
||||
i2c_del_adapter(&hdmi->i2c->adap);
|
||||
else
|
||||
|
@ -1817,7 +1817,7 @@ static int edid_block_tag(const void *_block)
|
||||
|
||||
static bool edid_block_is_zero(const void *edid)
|
||||
{
|
||||
return !memchr_inv(edid, 0, EDID_LENGTH);
|
||||
return mem_is_zero(edid, EDID_LENGTH);
|
||||
}
|
||||
|
||||
static bool drm_edid_eq(const struct drm_edid *drm_edid,
|
||||
|
@ -1339,6 +1339,9 @@ EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
|
||||
* @dsi: DSI peripheral device
|
||||
* @scanline: scanline to use as trigger
|
||||
*
|
||||
* This function is deprecated. Use mipi_dsi_dcs_set_tear_scanline_multi()
|
||||
* instead.
|
||||
*
|
||||
* Return: 0 on success or a negative error code on failure
|
||||
*/
|
||||
int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline)
|
||||
@ -1833,6 +1836,34 @@ void mipi_dsi_dcs_set_page_address_multi(struct mipi_dsi_multi_context *ctx,
|
||||
}
|
||||
EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address_multi);
|
||||
|
||||
/**
|
||||
* mipi_dsi_dcs_set_tear_scanline_multi() - set the scanline to use as trigger for
|
||||
* the Tearing Effect output signal of the display module
|
||||
* @ctx: Context for multiple DSI transactions
|
||||
* @scanline: scanline to use as trigger
|
||||
*
|
||||
* Like mipi_dsi_dcs_set_tear_scanline() but deals with errors in a way that
|
||||
* makes it convenient to make several calls in a row.
|
||||
*/
|
||||
void mipi_dsi_dcs_set_tear_scanline_multi(struct mipi_dsi_multi_context *ctx,
|
||||
u16 scanline)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (ctx->accum_err)
|
||||
return;
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_scanline(dsi, scanline);
|
||||
if (ret < 0) {
|
||||
ctx->accum_err = ret;
|
||||
dev_err(dev, "Failed to set tear scanline: %d\n",
|
||||
ctx->accum_err);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_scanline_multi);
|
||||
|
||||
static int mipi_dsi_drv_probe(struct device *dev)
|
||||
{
|
||||
struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
|
||||
|
@ -5184,7 +5184,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
|
||||
ack[3] |= DP_TUNNELING_IRQ;
|
||||
}
|
||||
|
||||
if (!memchr_inv(ack, 0, sizeof(ack)))
|
||||
if (mem_is_zero(ack, sizeof(ack)))
|
||||
break;
|
||||
|
||||
if (!intel_dp_ack_sink_irq_esi(intel_dp, ack))
|
||||
|
@ -1117,7 +1117,7 @@ const struct drm_edid *intel_opregion_get_edid(struct intel_connector *connector
|
||||
|
||||
/* Validity corresponds to number of 128-byte blocks */
|
||||
len = (opregion->asle_ext->phed & ASLE_PHED_EDID_VALID_MASK) * 128;
|
||||
if (!len || !memchr_inv(edid, 0, len))
|
||||
if (!len || mem_is_zero(edid, len))
|
||||
return NULL;
|
||||
|
||||
drm_edid = drm_edid_alloc(edid, len);
|
||||
|
@ -506,7 +506,7 @@ static int igt_dmabuf_export_vmap(void *arg)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memchr_inv(ptr, 0, dmabuf->size)) {
|
||||
if (!mem_is_zero(ptr, dmabuf->size)) {
|
||||
pr_err("Exported object not initialised to zero!\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
|
@ -668,7 +668,7 @@ pvr_ioctl_union_padding_check(void *instance, size_t union_offset,
|
||||
void *padding_start = ((u8 *)instance) + union_offset + member_size;
|
||||
size_t padding_size = union_size - member_size;
|
||||
|
||||
return !memchr_inv(padding_start, 0, padding_size);
|
||||
return mem_is_zero(padding_start, padding_size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -784,7 +784,8 @@ config DRM_PANEL_SHARP_LS060T1SX01
|
||||
config DRM_PANEL_SITRONIX_ST7701
|
||||
tristate "Sitronix ST7701 panel driver"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on SPI || DRM_MIPI_DSI
|
||||
select DRM_MIPI_DBI if SPI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable support for the Sitronix
|
||||
|
@ -121,19 +121,19 @@ struct ili9341_config {
|
||||
const struct drm_display_mode mode;
|
||||
/* ca: TODO: need comments for this register */
|
||||
u8 ca[ILI9341_CA_LEN];
|
||||
/* power_b: TODO: need comments for this register */
|
||||
/* power_b: Power control B (CFh) */
|
||||
u8 power_b[ILI9341_POWER_B_LEN];
|
||||
/* power_seq: TODO: need comments for this register */
|
||||
/* power_seq: Power on sequence control (EDh) */
|
||||
u8 power_seq[ILI9341_POWER_SEQ_LEN];
|
||||
/* dtca: TODO: need comments for this register */
|
||||
/* dtca: Driver timing control A (E8h) */
|
||||
u8 dtca[ILI9341_DTCA_LEN];
|
||||
/* dtcb: TODO: need comments for this register */
|
||||
/* dtcb: Driver timing control B (EAh) */
|
||||
u8 dtcb[ILI9341_DTCB_LEN];
|
||||
/* power_a: TODO: need comments for this register */
|
||||
/* power_a: Power control A (CBh) */
|
||||
u8 power_a[ILI9341_POWER_A_LEN];
|
||||
/* frc: Frame Rate Control (In Normal Mode/Full Colors) (B1h) */
|
||||
u8 frc[ILI9341_FRC_LEN];
|
||||
/* prc: TODO: need comments for this register */
|
||||
/* prc: Pump ratio control (F7h) */
|
||||
u8 prc;
|
||||
/* dfc_1: B6h DISCTRL (Display Function Control) */
|
||||
u8 dfc_1[ILI9341_DFC_1_LEN];
|
||||
@ -147,7 +147,7 @@ struct ili9341_config {
|
||||
u8 vcom_2;
|
||||
/* address_mode: Memory Access Control (36h) */
|
||||
u8 address_mode;
|
||||
/* g3amma_en: TODO: need comments for this register */
|
||||
/* g3amma_en: Enable 3G (F2h) */
|
||||
u8 g3amma_en;
|
||||
/* rgb_interface: RGB Interface Signal Control (B0h) */
|
||||
u8 rgb_interface;
|
||||
|
@ -31,8 +31,6 @@ struct jadard_panel_desc {
|
||||
bool reset_before_power_off_vcioo;
|
||||
unsigned int vcioo_to_lp11_delay_ms;
|
||||
unsigned int lp11_to_reset_delay_ms;
|
||||
unsigned int exit_sleep_to_display_on_delay_ms;
|
||||
unsigned int display_on_delay_ms;
|
||||
unsigned int backlight_off_to_display_off_delay_ms;
|
||||
unsigned int display_off_to_enter_sleep_delay_ms;
|
||||
unsigned int enter_sleep_to_reset_down_delay_ms;
|
||||
@ -66,26 +64,6 @@ static inline struct jadard *panel_to_jadard(struct drm_panel *panel)
|
||||
return container_of(panel, struct jadard, panel);
|
||||
}
|
||||
|
||||
static int jadard_enable(struct drm_panel *panel)
|
||||
{
|
||||
struct jadard *jadard = panel_to_jadard(panel);
|
||||
struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi };
|
||||
|
||||
msleep(120);
|
||||
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
|
||||
|
||||
if (jadard->desc->exit_sleep_to_display_on_delay_ms)
|
||||
mipi_dsi_msleep(&dsi_ctx, jadard->desc->exit_sleep_to_display_on_delay_ms);
|
||||
|
||||
mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
|
||||
|
||||
if (jadard->desc->display_on_delay_ms)
|
||||
mipi_dsi_msleep(&dsi_ctx, jadard->desc->display_on_delay_ms);
|
||||
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int jadard_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct jadard *jadard = panel_to_jadard(panel);
|
||||
@ -202,7 +180,6 @@ static const struct drm_panel_funcs jadard_funcs = {
|
||||
.disable = jadard_disable,
|
||||
.unprepare = jadard_unprepare,
|
||||
.prepare = jadard_prepare,
|
||||
.enable = jadard_enable,
|
||||
.get_modes = jadard_get_modes,
|
||||
.get_orientation = jadard_panel_get_orientation,
|
||||
};
|
||||
@ -382,6 +359,12 @@ static int radxa_display_8hd_ad002_init_cmds(struct jadard *jadard)
|
||||
|
||||
jd9365da_switch_page(&dsi_ctx, 0x00);
|
||||
|
||||
mipi_dsi_msleep(&dsi_ctx, 120);
|
||||
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
|
||||
|
||||
mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
|
||||
|
||||
return dsi_ctx.accum_err;
|
||||
};
|
||||
|
||||
@ -608,6 +591,12 @@ static int cz101b4001_init_cmds(struct jadard *jadard)
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE6, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xE7, 0x0C);
|
||||
|
||||
mipi_dsi_msleep(&dsi_ctx, 120);
|
||||
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
|
||||
|
||||
mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
|
||||
|
||||
return dsi_ctx.accum_err;
|
||||
};
|
||||
|
||||
@ -831,6 +820,16 @@ static int kingdisplay_kd101ne3_init_cmds(struct jadard *jadard)
|
||||
|
||||
jd9365da_switch_page(&dsi_ctx, 0x00);
|
||||
|
||||
mipi_dsi_msleep(&dsi_ctx, 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);
|
||||
|
||||
mipi_dsi_msleep(&dsi_ctx, 20);
|
||||
|
||||
return dsi_ctx.accum_err;
|
||||
};
|
||||
|
||||
@ -859,8 +858,6 @@ static const struct jadard_panel_desc kingdisplay_kd101ne3_40ti_desc = {
|
||||
.reset_before_power_off_vcioo = true,
|
||||
.vcioo_to_lp11_delay_ms = 5,
|
||||
.lp11_to_reset_delay_ms = 10,
|
||||
.exit_sleep_to_display_on_delay_ms = 120,
|
||||
.display_on_delay_ms = 20,
|
||||
.backlight_off_to_display_off_delay_ms = 100,
|
||||
.display_off_to_enter_sleep_delay_ms = 50,
|
||||
.enter_sleep_to_reset_down_delay_ms = 100,
|
||||
@ -876,22 +873,22 @@ static int melfas_lmfbx101117480_init_cmds(struct jadard *jadard)
|
||||
jd9365da_switch_page(&dsi_ctx, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xbf);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xd7);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xbf);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xd7);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x70);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x2d);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x2d);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x7e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfd);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x19);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x28);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x05);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x12);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x78);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x7e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x7f);
|
||||
@ -902,47 +899,47 @@ static int melfas_lmfbx101117480_init_cmds(struct jadard *jadard)
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x8e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x6a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x09);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x2e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x1a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x15);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x69);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x59);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x4e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x4c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x40);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x45);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x30);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x4a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x49);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x4a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x68);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x57);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x5b);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x4e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x49);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x73);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x56);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x43);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x38);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x36);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x28);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x2f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x19);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x32);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x31);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x31);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x4f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x3e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x47);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x36);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x31);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x24);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x12);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x69);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x59);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x4e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x4c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x40);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x45);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x30);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x4a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x49);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x4a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x68);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x57);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x5b);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x4e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x49);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x73);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x56);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x43);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x38);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x36);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x28);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x2f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x19);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x32);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x31);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x31);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x4f);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x3e);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x47);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x36);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x31);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x24);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x12);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x02);
|
||||
@ -1074,6 +1071,16 @@ static int melfas_lmfbx101117480_init_cmds(struct jadard *jadard)
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe7, 0x06);
|
||||
|
||||
mipi_dsi_msleep(&dsi_ctx, 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);
|
||||
|
||||
mipi_dsi_msleep(&dsi_ctx, 20);
|
||||
|
||||
return dsi_ctx.accum_err;
|
||||
};
|
||||
|
||||
@ -1102,8 +1109,6 @@ static const struct jadard_panel_desc melfas_lmfbx101117480_desc = {
|
||||
.reset_before_power_off_vcioo = true,
|
||||
.vcioo_to_lp11_delay_ms = 5,
|
||||
.lp11_to_reset_delay_ms = 10,
|
||||
.exit_sleep_to_display_on_delay_ms = 120,
|
||||
.display_on_delay_ms = 20,
|
||||
.backlight_off_to_display_off_delay_ms = 100,
|
||||
.display_off_to_enter_sleep_delay_ms = 50,
|
||||
.enter_sleep_to_reset_down_delay_ms = 100,
|
||||
|
@ -41,142 +41,89 @@ static void jdi_fhd_r63452_reset(struct jdi_fhd_r63452 *ctx)
|
||||
static int jdi_fhd_r63452_on(struct jdi_fhd_r63452 *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, 0xb0, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd6, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xec,
|
||||
0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
|
||||
0x13, 0x15, 0x68, 0x0b, 0xb5);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x03);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd6, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xec,
|
||||
0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
|
||||
0x13, 0x15, 0x68, 0x0b, 0xb5);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x03);
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set tear on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x77);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set pixel format: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mipi_dsi_dcs_set_pixel_format_multi(&dsi_ctx, 0x77);
|
||||
mipi_dsi_dcs_set_column_address_multi(&dsi_ctx, 0x0000, 0x0437);
|
||||
mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0x0000, 0x077f);
|
||||
mipi_dsi_dcs_set_tear_scanline_multi(&dsi_ctx, 0x0000);
|
||||
mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0x00ff);
|
||||
|
||||
ret = mipi_dsi_dcs_set_column_address(dsi, 0x0000, 0x0437);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set column address: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x84, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_set_page_address(dsi, 0x0000, 0x077f);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set page address: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 20);
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 80);
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0x0000);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set tear scanline: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x04);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x84, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc8, 0x11);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x03);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x00ff);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display brightness: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x84, 0x00);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
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(80);
|
||||
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x04);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0x84, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xc8, 0x11);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x03);
|
||||
|
||||
return 0;
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int jdi_fhd_r63452_off(struct jdi_fhd_r63452 *ctx)
|
||||
static void jdi_fhd_r63452_off(struct jdi_fhd_r63452 *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, 0xb0, 0x00);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xd6, 0x01);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xec,
|
||||
0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
|
||||
0x13, 0x15, 0x68, 0x0b, 0x95);
|
||||
mipi_dsi_generic_write_seq(dsi, 0xb0, 0x03);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd6, 0x01);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xec,
|
||||
0x64, 0xdc, 0xec, 0x3b, 0x52, 0x00, 0x0b, 0x0b,
|
||||
0x13, 0x15, 0x68, 0x0b, 0x95);
|
||||
mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x03);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
usleep_range(2000, 3000);
|
||||
|
||||
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(120);
|
||||
|
||||
return 0;
|
||||
mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
|
||||
mipi_dsi_usleep_range(&dsi_ctx, 2000, 3000);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 120);
|
||||
}
|
||||
|
||||
static int jdi_fhd_r63452_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct jdi_fhd_r63452 *ctx = to_jdi_fhd_r63452(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
jdi_fhd_r63452_reset(ctx);
|
||||
|
||||
ret = jdi_fhd_r63452_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
if (ret < 0)
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int jdi_fhd_r63452_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct jdi_fhd_r63452 *ctx = to_jdi_fhd_r63452(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = jdi_fhd_r63452_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
/*
|
||||
* NOTE: We don't return an error here as while the panel won't have
|
||||
* been cleanly turned off at least we've asserted the reset signal
|
||||
* so it should be safe to power it back on again later
|
||||
*/
|
||||
jdi_fhd_r63452_off(ctx);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/* Manufacturer specific Commands send via DSI */
|
||||
#define MANTIX_CMD_OTP_STOP_RELOAD_MIPI 0x41
|
||||
#define MANTIX_CMD_INT_CANCEL 0x4C
|
||||
#define MANTIX_CMD_INT_CANCEL 0x4c
|
||||
#define MANTIX_CMD_SPI_FINISH 0x90
|
||||
|
||||
struct mantix {
|
||||
@ -45,82 +45,57 @@ static inline struct mantix *panel_to_mantix(struct drm_panel *panel)
|
||||
return container_of(panel, struct mantix, panel);
|
||||
}
|
||||
|
||||
static int mantix_init_sequence(struct mantix *ctx)
|
||||
static void mantix_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
struct device *dev = ctx->dev;
|
||||
|
||||
/*
|
||||
* Init sequence was supplied by the panel vendor.
|
||||
*/
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5a);
|
||||
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_INT_CANCEL, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x03);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x80, 0xA9, 0x00);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, MANTIX_CMD_INT_CANCEL, 0x03);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5a, 0x03);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x80, 0xa9, 0x00);
|
||||
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x09);
|
||||
mipi_dsi_generic_write_seq(dsi, 0x80, 0x64, 0x00, 0x64, 0x00, 0x00);
|
||||
msleep(20);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5a, 0x09);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, 0x80, 0x64, 0x00, 0x64, 0x00, 0x00);
|
||||
mipi_dsi_msleep(dsi_ctx, 20);
|
||||
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_SPI_FINISH, 0xA5);
|
||||
mipi_dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x00, 0x2F);
|
||||
msleep(20);
|
||||
|
||||
dev_dbg(dev, "Panel init sequence done\n");
|
||||
return 0;
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, MANTIX_CMD_SPI_FINISH, 0xa5);
|
||||
mipi_dsi_generic_write_seq_multi(dsi_ctx, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x00, 0x2f);
|
||||
mipi_dsi_msleep(dsi_ctx, 20);
|
||||
}
|
||||
|
||||
static int mantix_enable(struct drm_panel *panel)
|
||||
{
|
||||
struct mantix *ctx = panel_to_mantix(panel);
|
||||
struct device *dev = ctx->dev;
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
|
||||
int ret;
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
|
||||
struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
|
||||
|
||||
ret = mantix_init_sequence(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mantix_init_sequence(&dsi_ctx);
|
||||
if (!dsi_ctx.accum_err)
|
||||
dev_dbg(ctx->dev, "Panel init sequence done\n");
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to exit sleep mode\n");
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 20);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret)
|
||||
return ret;
|
||||
usleep_range(10000, 12000);
|
||||
mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
|
||||
mipi_dsi_usleep_range(&dsi_ctx, 10000, 12000);
|
||||
|
||||
ret = mipi_dsi_turn_on_peripheral(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to turn on peripheral\n");
|
||||
return ret;
|
||||
}
|
||||
mipi_dsi_turn_on_peripheral_multi(&dsi_ctx);
|
||||
|
||||
return 0;
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int mantix_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct mantix *ctx = panel_to_mantix(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);
|
||||
mipi_dsi_dcs_enter_sleep_mode_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);
|
||||
|
||||
|
||||
return 0;
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int mantix_unprepare(struct drm_panel *panel)
|
||||
|
@ -2527,6 +2527,38 @@ static const struct panel_desc innolux_g070y2_l01 = {
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct display_timing innolux_g070ace_lh3_timing = {
|
||||
.pixelclock = { 25200000, 25400000, 35700000 },
|
||||
.hactive = { 800, 800, 800 },
|
||||
.hfront_porch = { 30, 32, 87 },
|
||||
.hback_porch = { 29, 31, 86 },
|
||||
.hsync_len = { 1, 1, 1 },
|
||||
.vactive = { 480, 480, 480 },
|
||||
.vfront_porch = { 4, 5, 65 },
|
||||
.vback_porch = { 3, 4, 65 },
|
||||
.vsync_len = { 1, 1, 1 },
|
||||
.flags = DISPLAY_FLAGS_DE_HIGH,
|
||||
};
|
||||
|
||||
static const struct panel_desc innolux_g070ace_lh3 = {
|
||||
.timings = &innolux_g070ace_lh3_timing,
|
||||
.num_timings = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 152,
|
||||
.height = 91,
|
||||
},
|
||||
.delay = {
|
||||
.prepare = 10,
|
||||
.enable = 450,
|
||||
.disable = 200,
|
||||
.unprepare = 510,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH,
|
||||
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode innolux_g070y2_t02_mode = {
|
||||
.clock = 33333,
|
||||
.hdisplay = 800,
|
||||
@ -3486,6 +3518,39 @@ static const struct panel_desc olimex_lcd_olinuxino_43ts = {
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
};
|
||||
|
||||
static const struct display_timing ontat_kd50g21_40nt_a1_timing = {
|
||||
.pixelclock = { 30000000, 30000000, 50000000 },
|
||||
.hactive = { 800, 800, 800 },
|
||||
.hfront_porch = { 1, 40, 255 },
|
||||
.hback_porch = { 1, 40, 87 },
|
||||
.hsync_len = { 1, 48, 87 },
|
||||
.vactive = { 480, 480, 480 },
|
||||
.vfront_porch = { 1, 13, 255 },
|
||||
.vback_porch = { 1, 29, 29 },
|
||||
.vsync_len = { 3, 3, 31 },
|
||||
.flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
|
||||
DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE,
|
||||
};
|
||||
|
||||
static const struct panel_desc ontat_kd50g21_40nt_a1 = {
|
||||
.timings = &ontat_kd50g21_40nt_a1_timing,
|
||||
.num_timings = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 108,
|
||||
.height = 65,
|
||||
},
|
||||
.delay = {
|
||||
.prepare = 147, /* 5 VSDs */
|
||||
.enable = 147, /* 5 VSDs */
|
||||
.disable = 88, /* 3 VSDs */
|
||||
.unprepare = 117, /* 4 VSDs */
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE,
|
||||
.connector_type = DRM_MODE_CONNECTOR_DPI,
|
||||
};
|
||||
|
||||
/*
|
||||
* 800x480 CVT. The panel appears to be quite accepting, at least as far as
|
||||
* pixel clocks, but this is the timing that was being used in the Adafruit
|
||||
@ -4734,6 +4799,9 @@ static const struct of_device_id platform_of_match[] = {
|
||||
}, {
|
||||
.compatible = "innolux,g070ace-l01",
|
||||
.data = &innolux_g070ace_l01,
|
||||
}, {
|
||||
.compatible = "innolux,g070ace-lh3",
|
||||
.data = &innolux_g070ace_lh3,
|
||||
}, {
|
||||
.compatible = "innolux,g070y2-l01",
|
||||
.data = &innolux_g070y2_l01,
|
||||
@ -4845,6 +4913,9 @@ static const struct of_device_id platform_of_match[] = {
|
||||
}, {
|
||||
.compatible = "olimex,lcd-olinuxino-43-ts",
|
||||
.data = &olimex_lcd_olinuxino_43ts,
|
||||
}, {
|
||||
.compatible = "ontat,kd50g21-40nt-a1",
|
||||
.data = &ontat_kd50g21_40nt_a1,
|
||||
}, {
|
||||
.compatible = "ontat,yx700wv03",
|
||||
.data = &ontat_yx700wv03,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -69,7 +69,7 @@ bool udl_probe_edid(struct udl_device *udl)
|
||||
* The adapter sends all-zeros if no monitor has been
|
||||
* connected. We consider anything else a connection.
|
||||
*/
|
||||
return !!memchr_inv(hdr, 0, sizeof(hdr));
|
||||
return !mem_is_zero(hdr, sizeof(hdr));
|
||||
}
|
||||
|
||||
const struct drm_edid *udl_edid_read(struct drm_connector *connector)
|
||||
|
@ -469,7 +469,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
|
||||
|
||||
if (IS_ERR(dma_obj)) {
|
||||
struct drm_printer p = drm_info_printer(vc4->base.dev);
|
||||
DRM_ERROR("Failed to allocate from GEM DMA helper:\n");
|
||||
drm_err(dev, "Failed to allocate from GEM DMA helper:\n");
|
||||
vc4_bo_stats_print(&p, vc4);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
@ -702,7 +702,7 @@ static struct dma_buf *vc4_prime_export(struct drm_gem_object *obj, int flags)
|
||||
*/
|
||||
ret = vc4_bo_inc_usecnt(bo);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to increment BO usecnt\n");
|
||||
drm_err(obj->dev, "Failed to increment BO usecnt\n");
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
@ -1050,10 +1050,10 @@ static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused)
|
||||
|
||||
for (i = 0; i < vc4->num_labels; i++) {
|
||||
if (vc4->bo_labels[i].num_allocated) {
|
||||
DRM_ERROR("Destroying BO cache with %d %s "
|
||||
"BOs still allocated\n",
|
||||
vc4->bo_labels[i].num_allocated,
|
||||
vc4->bo_labels[i].name);
|
||||
drm_err(dev, "Destroying BO cache with %d %s "
|
||||
"BOs still allocated\n",
|
||||
vc4->bo_labels[i].num_allocated,
|
||||
vc4->bo_labels[i].name);
|
||||
}
|
||||
|
||||
if (is_user_label(i))
|
||||
@ -1083,7 +1083,7 @@ int vc4_label_bo_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
gem_obj = drm_gem_object_lookup(file_priv, args->handle);
|
||||
if (!gem_obj) {
|
||||
DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
|
||||
drm_err(dev, "Failed to look up GEM BO %d\n", args->handle);
|
||||
kfree(name);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -199,8 +199,8 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
|
||||
DPI_FORMAT);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown media bus format %d\n",
|
||||
bus_format);
|
||||
drm_err(dev, "Unknown media bus format %d\n",
|
||||
bus_format);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -236,11 +236,11 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
|
||||
|
||||
ret = clk_set_rate(dpi->pixel_clock, mode->clock * 1000);
|
||||
if (ret)
|
||||
DRM_ERROR("Failed to set clock rate: %d\n", ret);
|
||||
drm_err(dev, "Failed to set clock rate: %d\n", ret);
|
||||
|
||||
ret = clk_prepare_enable(dpi->pixel_clock);
|
||||
if (ret)
|
||||
DRM_ERROR("Failed to set clock rate: %d\n", ret);
|
||||
drm_err(dev, "Failed to set clock rate: %d\n", ret);
|
||||
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
@ -339,7 +339,7 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
|
||||
if (IS_ERR(dpi->core_clock)) {
|
||||
ret = PTR_ERR(dpi->core_clock);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
DRM_ERROR("Failed to get core clock: %d\n", ret);
|
||||
drm_err(drm, "Failed to get core clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -347,13 +347,13 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
|
||||
if (IS_ERR(dpi->pixel_clock)) {
|
||||
ret = PTR_ERR(dpi->pixel_clock);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
DRM_ERROR("Failed to get pixel clock: %d\n", ret);
|
||||
drm_err(drm, "Failed to get pixel clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dpi->core_clock);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to turn on core clock: %d\n", ret);
|
||||
drm_err(drm, "Failed to turn on core clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -613,6 +613,7 @@ struct vc4_dsi {
|
||||
static inline void
|
||||
dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val)
|
||||
{
|
||||
struct drm_device *drm = dsi->bridge.dev;
|
||||
struct dma_chan *chan = dsi->reg_dma_chan;
|
||||
struct dma_async_tx_descriptor *tx;
|
||||
dma_cookie_t cookie;
|
||||
@ -633,19 +634,19 @@ dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val)
|
||||
dsi->reg_dma_paddr,
|
||||
4, 0);
|
||||
if (!tx) {
|
||||
DRM_ERROR("Failed to set up DMA register write\n");
|
||||
drm_err(drm, "Failed to set up DMA register write\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cookie = tx->tx_submit(tx);
|
||||
ret = dma_submit_error(cookie);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to submit DMA: %d\n", ret);
|
||||
drm_err(drm, "Failed to submit DMA: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
ret = dma_sync_wait(chan, cookie);
|
||||
if (ret)
|
||||
DRM_ERROR("Failed to wait for DMA: %d\n", ret);
|
||||
drm_err(drm, "Failed to wait for DMA: %d\n", ret);
|
||||
}
|
||||
|
||||
#define DSI_READ(offset) \
|
||||
@ -893,7 +894,7 @@ static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
|
||||
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->variant->port);
|
||||
drm_err(bridge->dev, "Failed to runtime PM enable on DSI%d\n", dsi->variant->port);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -986,13 +987,14 @@ static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
|
||||
|
||||
ret = clk_prepare_enable(dsi->escape_clock);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to turn on DSI escape clock: %d\n", ret);
|
||||
drm_err(bridge->dev, "Failed to turn on DSI escape clock: %d\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dsi->pll_phy_clock);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to turn on DSI PLL: %d\n", ret);
|
||||
drm_err(bridge->dev, "Failed to turn on DSI PLL: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1014,7 +1016,7 @@ static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
|
||||
|
||||
ret = clk_prepare_enable(dsi->pixel_clock);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to turn on DSI pixel clock: %d\n", ret);
|
||||
drm_err(bridge->dev, "Failed to turn on DSI pixel clock: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1172,6 +1174,7 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
|
||||
const struct mipi_dsi_msg *msg)
|
||||
{
|
||||
struct vc4_dsi *dsi = host_to_dsi(host);
|
||||
struct drm_device *drm = dsi->bridge.dev;
|
||||
struct mipi_dsi_packet packet;
|
||||
u32 pkth = 0, pktc = 0;
|
||||
int i, ret;
|
||||
@ -1303,8 +1306,8 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
|
||||
DSI_RXPKT1H_BC_PARAM);
|
||||
|
||||
if (rxlen != msg->rx_len) {
|
||||
DRM_ERROR("DSI returned %db, expecting %db\n",
|
||||
rxlen, (int)msg->rx_len);
|
||||
drm_err(drm, "DSI returned %db, expecting %db\n",
|
||||
rxlen, (int)msg->rx_len);
|
||||
ret = -ENXIO;
|
||||
goto reset_fifo_and_return;
|
||||
}
|
||||
@ -1326,7 +1329,7 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
|
||||
return ret;
|
||||
|
||||
reset_fifo_and_return:
|
||||
DRM_ERROR("DSI transfer failed, resetting: %d\n", ret);
|
||||
drm_err(drm, "DSI transfer failed, resetting: %d\n", ret);
|
||||
|
||||
DSI_PORT_WRITE(TXPKT1C, DSI_PORT_READ(TXPKT1C) & ~DSI_TXPKT1C_CMD_EN);
|
||||
udelay(1);
|
||||
@ -1468,7 +1471,8 @@ static void dsi_handle_error(struct vc4_dsi *dsi,
|
||||
if (!(stat & bit))
|
||||
return;
|
||||
|
||||
DRM_ERROR("DSI%d: %s error\n", dsi->variant->port, type);
|
||||
drm_err(dsi->bridge.dev, "DSI%d: %s error\n", dsi->variant->port,
|
||||
type);
|
||||
*ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -1687,7 +1691,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
|
||||
&dsi->reg_dma_paddr,
|
||||
GFP_KERNEL);
|
||||
if (!dsi->reg_dma_mem) {
|
||||
DRM_ERROR("Failed to get DMA memory\n");
|
||||
drm_err(drm, "Failed to get DMA memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -1702,8 +1706,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
|
||||
if (IS_ERR(dsi->reg_dma_chan)) {
|
||||
ret = PTR_ERR(dsi->reg_dma_chan);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
DRM_ERROR("Failed to get DMA channel: %d\n",
|
||||
ret);
|
||||
drm_err(drm, "Failed to get DMA channel: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -832,8 +832,8 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
|
||||
*/
|
||||
temp = kvmalloc_array(temp_size, 1, GFP_KERNEL);
|
||||
if (!temp) {
|
||||
DRM_ERROR("Failed to allocate storage for copying "
|
||||
"in bin/render CLs.\n");
|
||||
drm_err(dev, "Failed to allocate storage for copying "
|
||||
"in bin/render CLs.\n");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
@ -866,7 +866,7 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
|
||||
|
||||
bo = vc4_bo_create(dev, exec_size, true, VC4_BO_TYPE_BCL);
|
||||
if (IS_ERR(bo)) {
|
||||
DRM_ERROR("Couldn't allocate BO for binning\n");
|
||||
drm_err(dev, "Couldn't allocate BO for binning\n");
|
||||
ret = PTR_ERR(bo);
|
||||
goto fail;
|
||||
}
|
||||
@ -1153,10 +1153,9 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
|
||||
}
|
||||
|
||||
exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);
|
||||
if (!exec) {
|
||||
DRM_ERROR("malloc failure on exec struct\n");
|
||||
if (!exec)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
exec->dev = vc4;
|
||||
|
||||
ret = vc4_v3d_pm_get(vc4);
|
||||
|
@ -429,6 +429,7 @@ static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector,
|
||||
{
|
||||
struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
|
||||
enum drm_connector_status status = connector_status_disconnected;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* NOTE: This function should really take vc4_hdmi->mutex, but
|
||||
@ -441,7 +442,12 @@ static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector,
|
||||
* the lock for now.
|
||||
*/
|
||||
|
||||
WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev));
|
||||
ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev);
|
||||
if (ret) {
|
||||
drm_err_once(connector->dev, "Failed to retain HDMI power domain: %d\n",
|
||||
ret);
|
||||
return connector_status_unknown;
|
||||
}
|
||||
|
||||
if (vc4_hdmi->hpd_gpio) {
|
||||
if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio))
|
||||
@ -698,7 +704,7 @@ static int vc4_hdmi_write_infoframe(struct drm_connector *connector,
|
||||
|
||||
ret = vc4_hdmi_stop_packet(vc4_hdmi, type, true);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret);
|
||||
drm_err(drm, "Failed to wait for infoframe to go idle: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -734,7 +740,7 @@ static int vc4_hdmi_write_infoframe(struct drm_connector *connector,
|
||||
ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
|
||||
BIT(packet_id)), 100);
|
||||
if (ret)
|
||||
DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
|
||||
drm_err(drm, "Failed to wait for infoframe to start: %d\n", ret);
|
||||
|
||||
out:
|
||||
drm_dev_exit(idx);
|
||||
@ -895,7 +901,7 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
|
||||
|
||||
ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
|
||||
if (ret < 0)
|
||||
DRM_ERROR("Failed to release power domain: %d\n", ret);
|
||||
drm_err(drm, "Failed to release power domain: %d\n", ret);
|
||||
|
||||
drm_dev_exit(idx);
|
||||
|
||||
@ -1437,7 +1443,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
|
||||
|
||||
ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("Failed to retain power domain: %d\n", ret);
|
||||
drm_err(drm, "Failed to retain power domain: %d\n", ret);
|
||||
goto err_dev_exit;
|
||||
}
|
||||
|
||||
@ -1462,19 +1468,19 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
|
||||
div_u64(tmds_char_rate, 100) * 101);
|
||||
ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
|
||||
drm_err(drm, "Failed to set HSM clock rate: %d\n", ret);
|
||||
goto err_put_runtime_pm;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
|
||||
drm_err(drm, "Failed to set pixel clock rate: %d\n", ret);
|
||||
goto err_put_runtime_pm;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(vc4_hdmi->pixel_clock);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
|
||||
drm_err(drm, "Failed to turn on pixel clock: %d\n", ret);
|
||||
goto err_put_runtime_pm;
|
||||
}
|
||||
|
||||
@ -1490,13 +1496,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
|
||||
|
||||
ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret);
|
||||
drm_err(drm, "Failed to set pixel bvb clock rate: %d\n", ret);
|
||||
goto err_disable_pixel_clock;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret);
|
||||
drm_err(drm, "Failed to turn on pixel bvb clock: %d\n", ret);
|
||||
goto err_disable_pixel_clock;
|
||||
}
|
||||
|
||||
@ -2945,13 +2951,13 @@ static int vc4_hdmi_init_resources(struct drm_device *drm,
|
||||
if (IS_ERR(vc4_hdmi->pixel_clock)) {
|
||||
ret = PTR_ERR(vc4_hdmi->pixel_clock);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
DRM_ERROR("Failed to get pixel clock\n");
|
||||
drm_err(drm, "Failed to get pixel clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
|
||||
if (IS_ERR(vc4_hdmi->hsm_clock)) {
|
||||
DRM_ERROR("Failed to get HDMI state machine clock\n");
|
||||
drm_err(drm, "Failed to get HDMI state machine clock\n");
|
||||
return PTR_ERR(vc4_hdmi->hsm_clock);
|
||||
}
|
||||
vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock;
|
||||
@ -3035,31 +3041,31 @@ static int vc5_hdmi_init_resources(struct drm_device *drm,
|
||||
|
||||
vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
|
||||
if (IS_ERR(vc4_hdmi->hsm_clock)) {
|
||||
DRM_ERROR("Failed to get HDMI state machine clock\n");
|
||||
drm_err(drm, "Failed to get HDMI state machine clock\n");
|
||||
return PTR_ERR(vc4_hdmi->hsm_clock);
|
||||
}
|
||||
|
||||
vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb");
|
||||
if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) {
|
||||
DRM_ERROR("Failed to get pixel bvb clock\n");
|
||||
drm_err(drm, "Failed to get pixel bvb clock\n");
|
||||
return PTR_ERR(vc4_hdmi->pixel_bvb_clock);
|
||||
}
|
||||
|
||||
vc4_hdmi->audio_clock = devm_clk_get(dev, "audio");
|
||||
if (IS_ERR(vc4_hdmi->audio_clock)) {
|
||||
DRM_ERROR("Failed to get audio clock\n");
|
||||
drm_err(drm, "Failed to get audio clock\n");
|
||||
return PTR_ERR(vc4_hdmi->audio_clock);
|
||||
}
|
||||
|
||||
vc4_hdmi->cec_clock = devm_clk_get(dev, "cec");
|
||||
if (IS_ERR(vc4_hdmi->cec_clock)) {
|
||||
DRM_ERROR("Failed to get CEC clock\n");
|
||||
drm_err(drm, "Failed to get CEC clock\n");
|
||||
return PTR_ERR(vc4_hdmi->cec_clock);
|
||||
}
|
||||
|
||||
vc4_hdmi->reset = devm_reset_control_get(dev, NULL);
|
||||
if (IS_ERR(vc4_hdmi->reset)) {
|
||||
DRM_ERROR("Failed to get HDMI reset line\n");
|
||||
drm_err(drm, "Failed to get HDMI reset line\n");
|
||||
return PTR_ERR(vc4_hdmi->reset);
|
||||
}
|
||||
|
||||
@ -3215,14 +3221,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
|
||||
if (!ddc_node) {
|
||||
DRM_ERROR("Failed to find ddc node in device tree\n");
|
||||
drm_err(drm, "Failed to find ddc node in device tree\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
|
||||
of_node_put(ddc_node);
|
||||
if (!vc4_hdmi->ddc) {
|
||||
DRM_DEBUG("Failed to get ddc i2c adapter by node\n");
|
||||
drm_err(drm, "Failed to get ddc i2c adapter by node\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
|
@ -191,8 +191,8 @@ static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs,
|
||||
|
||||
ret = drm_mm_insert_node(&hvs->dlist_mm, space, VC4_KERNEL_DWORDS);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to allocate space for filter kernel: %d\n",
|
||||
ret);
|
||||
drm_err(&hvs->vc4->base, "Failed to allocate space for filter kernel: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ vc4_overflow_mem_work(struct work_struct *work)
|
||||
|
||||
bin_bo_slot = vc4_v3d_get_bin_slot(vc4);
|
||||
if (bin_bo_slot < 0) {
|
||||
DRM_ERROR("Couldn't allocate binner overflow mem\n");
|
||||
drm_err(&vc4->base, "Couldn't allocate binner overflow mem\n");
|
||||
goto complete;
|
||||
}
|
||||
|
||||
|
@ -441,21 +441,9 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
|
||||
vc4->v3d = v3d;
|
||||
v3d->vc4 = vc4;
|
||||
|
||||
v3d->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(v3d->clk)) {
|
||||
int ret = PTR_ERR(v3d->clk);
|
||||
|
||||
if (ret == -ENOENT) {
|
||||
/* bcm2835 didn't have a clock reference in the DT. */
|
||||
ret = 0;
|
||||
v3d->clk = NULL;
|
||||
} else {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to get V3D clock: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
v3d->clk = devm_clk_get_optional(dev, NULL);
|
||||
if (IS_ERR(v3d->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(v3d->clk), "Failed to get V3D clock\n");
|
||||
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
@ -471,8 +459,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
|
||||
return ret;
|
||||
|
||||
if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) {
|
||||
DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n",
|
||||
V3D_READ(V3D_IDENT0), V3D_EXPECTED_IDENT0);
|
||||
drm_err(drm, "V3D_IDENT0 read 0x%08x instead of 0x%08x\n",
|
||||
V3D_READ(V3D_IDENT0), V3D_EXPECTED_IDENT0);
|
||||
ret = -EINVAL;
|
||||
goto err_put_runtime_pm;
|
||||
}
|
||||
@ -485,7 +473,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
ret = vc4_irq_install(drm, vc4->irq);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to install IRQ handler\n");
|
||||
drm_err(drm, "Failed to install IRQ handler\n");
|
||||
goto err_put_runtime_pm;
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ utile_width(int cpp)
|
||||
case 8:
|
||||
return 2;
|
||||
default:
|
||||
DRM_ERROR("unknown cpp: %d\n", cpp);
|
||||
pr_err("unknown cpp: %d\n", cpp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -82,7 +82,7 @@ utile_height(int cpp)
|
||||
case 8:
|
||||
return 4;
|
||||
default:
|
||||
DRM_ERROR("unknown cpp: %d\n", cpp);
|
||||
pr_err("unknown cpp: %d\n", cpp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -390,8 +390,8 @@ validate_tile_binning_config(VALIDATE_ARGS)
|
||||
bin_slot = vc4_v3d_get_bin_slot(vc4);
|
||||
if (bin_slot < 0) {
|
||||
if (bin_slot != -EINTR && bin_slot != -ERESTARTSYS) {
|
||||
DRM_ERROR("Failed to allocate binner memory: %d\n",
|
||||
bin_slot);
|
||||
drm_err(dev, "Failed to allocate binner memory: %d\n",
|
||||
bin_slot);
|
||||
}
|
||||
return bin_slot;
|
||||
}
|
||||
|
@ -557,7 +557,7 @@ static void vc4_vec_encoder_disable(struct drm_encoder *encoder,
|
||||
|
||||
ret = pm_runtime_put(&vec->pdev->dev);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("Failed to release power domain: %d\n", ret);
|
||||
drm_err(drm, "Failed to release power domain: %d\n", ret);
|
||||
goto err_dev_exit;
|
||||
}
|
||||
|
||||
@ -591,7 +591,7 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder,
|
||||
|
||||
ret = pm_runtime_resume_and_get(&vec->pdev->dev);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("Failed to retain power domain: %d\n", ret);
|
||||
drm_err(drm, "Failed to retain power domain: %d\n", ret);
|
||||
goto err_dev_exit;
|
||||
}
|
||||
|
||||
@ -604,13 +604,13 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder,
|
||||
*/
|
||||
ret = clk_set_rate(vec->clock, 108000000);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to set clock rate: %d\n", ret);
|
||||
drm_err(drm, "Failed to set clock rate: %d\n", ret);
|
||||
goto err_put_runtime_pm;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(vec->clock);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to turn on core clock: %d\n", ret);
|
||||
drm_err(drm, "Failed to turn on core clock: %d\n", ret);
|
||||
goto err_put_runtime_pm;
|
||||
}
|
||||
|
||||
@ -806,7 +806,7 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
|
||||
if (IS_ERR(vec->clock)) {
|
||||
ret = PTR_ERR(vec->clock);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
DRM_ERROR("Failed to get clock: %d\n", ret);
|
||||
drm_err(drm, "Failed to get clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -375,6 +375,8 @@ void mipi_dsi_dcs_set_column_address_multi(struct mipi_dsi_multi_context *ctx,
|
||||
u16 start, u16 end);
|
||||
void mipi_dsi_dcs_set_page_address_multi(struct mipi_dsi_multi_context *ctx,
|
||||
u16 start, u16 end);
|
||||
void mipi_dsi_dcs_set_tear_scanline_multi(struct mipi_dsi_multi_context *ctx,
|
||||
u16 scanline);
|
||||
|
||||
/**
|
||||
* mipi_dsi_generic_write_seq - transmit data using a generic write packet
|
||||
|
@ -279,6 +279,18 @@ static inline void memcpy_flushcache(void *dst, const void *src, size_t cnt)
|
||||
void *memchr_inv(const void *s, int c, size_t n);
|
||||
char *strreplace(char *str, char old, char new);
|
||||
|
||||
/**
|
||||
* mem_is_zero - Check if an area of memory is all 0's.
|
||||
* @s: The memory area
|
||||
* @n: The size of the area
|
||||
*
|
||||
* Return: True if the area of memory is all 0's.
|
||||
*/
|
||||
static inline bool mem_is_zero(const void *s, size_t n)
|
||||
{
|
||||
return !memchr_inv(s, 0, n);
|
||||
}
|
||||
|
||||
extern void kfree_const(const void *x);
|
||||
|
||||
extern char *kstrdup(const char *s, gfp_t gfp) __malloc;
|
||||
|
Loading…
Reference in New Issue
Block a user