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:
Daniel Vetter 2024-08-27 12:25:26 +02:00
commit f9ae00b1cf
41 changed files with 1805 additions and 1453 deletions

View File

@ -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

View File

@ -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 = <&reg_lcd>;
IOVCC-supply = <&reg_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>;
};
};
};
};

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View 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;
}

View 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;
}

View File

@ -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;
}

View File

@ -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,

View File

@ -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) &&

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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))

View File

@ -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);

View File

@ -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;

View File

@ -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);
}
/**

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;