Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
12aa446
drm: Call drm_atomic_helper_shutdown() at shutdown time for misc drivers
dianders Sep 1, 2023
cc62847
drm/ast: Implement polling for VGA and SIL164 connectors
tdz Mar 25, 2024
4fae231
drm/hisilicon/hibmc: convert to struct drm_edid
jnikula May 14, 2024
a7fdc04
drm/hisilicon/hibmc: Use video aperture helpers
tdz Sep 30, 2024
019af9a
drm/hisilicon/hibmc: add dp aux in hibmc drivers
mark1188-ui Jan 3, 2025
bd0dc7c
drm/hisilicon/hibmc: add dp link moduel in hibmc drivers
mark1188-ui Jan 3, 2025
5c070fa
drm/hisilicon/hibmc: add dp hw moduel in hibmc driver
mark1188-ui Jan 3, 2025
4df5338
drm/hisilicon/hibmc: refactored struct hibmc_drm_private
mark1188-ui Jan 3, 2025
db270b9
drm/hisilicon/hibmc: add dp module in hibmc
mark1188-ui Jan 3, 2025
2b56278
drm/hisilicon/hibmc: select CONFIG_DRM_DISPLAY_DP_HELPER
arndb Jan 27, 2025
4ad1393
drm/hisilicon/hibmc: Restructuring the header dp_reg.h
mark1188-ui Mar 31, 2025
71bb50c
drm/hisilicon/hibmc: Add dp serdes cfg to adjust serdes rate, voltage…
mark1188-ui Mar 31, 2025
cc8241c
drm/hisilicon/hibmc: Add dp serdes cfg in dp process
mark1188-ui Mar 31, 2025
412a152
drm/hisilicon/hibmc: Refactor the member of drm_aux in struct hibmc_dp
mark1188-ui Mar 31, 2025
4517de1
drm/hisilicon/hibmc: Getting connector info and EDID by using AUX cha…
mark1188-ui Mar 31, 2025
ab5661f
drm/hisilicon/hibmc: Add colorbar-cfg feature and its debugfs file
mark1188-ui Mar 31, 2025
512a7e5
drm/hisilicon/hibmc: Enable this hot plug detect of irq feature
mark1188-ui Mar 31, 2025
a570024
drm/hisilicon/hibmc: Add MSI irq getting and requesting for HPD
mark1188-ui Mar 31, 2025
b60096d
drm/hisilicon/hibmc: Add vga connector detect functions
mark1188-ui Mar 31, 2025
acb9901
drm/hisilicon/hibmc: fix the i2c device resource leak when vdac init …
mark1188-ui Aug 13, 2025
f9c9171
drm/hisilicon/hibmc: fix irq_request()'s irq name variable is local
mark1188-ui Aug 13, 2025
79002ef
drm/hisilicon/hibmc: fix the hibmc loaded failed bug
mark1188-ui Aug 13, 2025
b76407b
drm/hisilicon/hibmc: fix rare monitors cannot display problem
mark1188-ui Aug 13, 2025
374edd1
drm/hisilicon/hibmc: fix dp and vga cannot show together
mark1188-ui Aug 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions drivers/gpu/drm/arm/display/komeda/komeda_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ static void komeda_platform_remove(struct platform_device *pdev)
devm_kfree(dev, mdrv);
}

static void komeda_platform_shutdown(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct komeda_drv *mdrv = dev_get_drvdata(dev);

komeda_kms_shutdown(mdrv->kms);
}

static int komeda_platform_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
Expand Down Expand Up @@ -142,6 +150,7 @@ static const struct dev_pm_ops komeda_pm_ops = {
static struct platform_driver komeda_platform_driver = {
.probe = komeda_platform_probe,
.remove_new = komeda_platform_remove,
.shutdown = komeda_platform_shutdown,
.driver = {
.name = "komeda",
.of_match_table = komeda_of_match,
Expand Down
7 changes: 7 additions & 0 deletions drivers/gpu/drm/arm/display/komeda/komeda_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,3 +344,10 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
komeda_kms_cleanup_private_objs(kms);
drm->dev_private = NULL;
}

void komeda_kms_shutdown(struct komeda_kms_dev *kms)
{
struct drm_device *drm = &kms->base;

drm_atomic_helper_shutdown(drm);
}
1 change: 1 addition & 0 deletions drivers/gpu/drm/arm/display/komeda/komeda_kms.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,5 +190,6 @@ void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,

struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev);
void komeda_kms_detach(struct komeda_kms_dev *kms);
void komeda_kms_shutdown(struct komeda_kms_dev *kms);

#endif /*_KOMEDA_KMS_H_*/
6 changes: 6 additions & 0 deletions drivers/gpu/drm/arm/hdlcd_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,11 @@ static void hdlcd_remove(struct platform_device *pdev)
component_master_del(&pdev->dev, &hdlcd_master_ops);
}

static void hdlcd_shutdown(struct platform_device *pdev)
{
drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
}

static const struct of_device_id hdlcd_of_match[] = {
{ .compatible = "arm,hdlcd" },
{},
Expand Down Expand Up @@ -399,6 +404,7 @@ static SIMPLE_DEV_PM_OPS(hdlcd_pm_ops, hdlcd_pm_suspend, hdlcd_pm_resume);
static struct platform_driver hdlcd_platform_driver = {
.probe = hdlcd_probe,
.remove_new = hdlcd_remove,
.shutdown = hdlcd_shutdown,
.driver = {
.name = "hdlcd",
.pm = &hdlcd_pm_ops,
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/arm/malidp_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,11 @@ static void malidp_platform_remove(struct platform_device *pdev)
component_master_del(&pdev->dev, &malidp_master_ops);
}

static void malidp_platform_shutdown(struct platform_device *pdev)
{
drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
}

static int __maybe_unused malidp_pm_suspend(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
Expand Down Expand Up @@ -982,6 +987,7 @@ static const struct dev_pm_ops malidp_pm_ops = {
static struct platform_driver malidp_platform_driver = {
.probe = malidp_platform_probe,
.remove_new = malidp_platform_remove,
.shutdown = malidp_platform_shutdown,
.driver = {
.name = "mali-dp",
.pm = &malidp_pm_ops,
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/ast/ast_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ static void ast_pci_remove(struct pci_dev *pdev)
drm_atomic_helper_shutdown(dev);
}

static void ast_pci_shutdown(struct pci_dev *pdev)
{
drm_atomic_helper_shutdown(pci_get_drvdata(pdev));
}

static int ast_drm_freeze(struct drm_device *dev)
{
int error;
Expand Down Expand Up @@ -209,6 +214,7 @@ static struct pci_driver ast_pci_driver = {
.id_table = ast_pciidlist,
.probe = ast_pci_probe,
.remove = ast_pci_remove,
.shutdown = ast_pci_shutdown,
.driver.pm = &ast_pm_ops,
};

Expand Down
6 changes: 4 additions & 2 deletions drivers/gpu/drm/ast/ast_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1382,6 +1382,7 @@ static int ast_vga_connector_helper_get_modes(struct drm_connector *connector)

static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs = {
.get_modes = ast_vga_connector_helper_get_modes,
.detect_ctx = drm_connector_helper_detect_from_ddc,
};

static const struct drm_connector_funcs ast_vga_connector_funcs = {
Expand Down Expand Up @@ -1417,7 +1418,7 @@ static int ast_vga_connector_init(struct drm_device *dev,
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;

connector->polled = DRM_CONNECTOR_POLL_CONNECT;
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;

return 0;
}
Expand Down Expand Up @@ -1488,6 +1489,7 @@ static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector

static const struct drm_connector_helper_funcs ast_sil164_connector_helper_funcs = {
.get_modes = ast_sil164_connector_helper_get_modes,
.detect_ctx = drm_connector_helper_detect_from_ddc,
};

static const struct drm_connector_funcs ast_sil164_connector_funcs = {
Expand Down Expand Up @@ -1523,7 +1525,7 @@ static int ast_sil164_connector_init(struct drm_device *dev,
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;

connector->polled = DRM_CONNECTOR_POLL_CONNECT;
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;

return 0;
}
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,11 @@ static void atmel_hlcdc_dc_drm_remove(struct platform_device *pdev)
drm_dev_put(ddev);
}

static void atmel_hlcdc_dc_drm_shutdown(struct platform_device *pdev)
{
drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
}

static int atmel_hlcdc_dc_drm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
Expand Down Expand Up @@ -825,6 +830,7 @@ static const struct of_device_id atmel_hlcdc_dc_of_match[] = {
static struct platform_driver atmel_hlcdc_dc_platform_driver = {
.probe = atmel_hlcdc_dc_drm_probe,
.remove_new = atmel_hlcdc_dc_drm_remove,
.shutdown = atmel_hlcdc_dc_drm_shutdown,
.driver = {
.name = "atmel-hlcdc-display-controller",
.pm = pm_sleep_ptr(&atmel_hlcdc_dc_drm_pm_ops),
Expand Down
29 changes: 29 additions & 0 deletions drivers/gpu/drm/drm_probe_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1313,3 +1313,32 @@ int drm_connector_helper_tv_get_modes(struct drm_connector *connector)
return i;
}
EXPORT_SYMBOL(drm_connector_helper_tv_get_modes);

/**
* drm_connector_helper_detect_from_ddc - Read EDID and detect connector status.
* @connector: The connector
* @ctx: Acquire context
* @force: Perform screen-destructive operations, if necessary
*
* Detects the connector status by reading the EDID using drm_probe_ddc(),
* which requires connector->ddc to be set. Returns connector_status_connected
* on success or connector_status_disconnected on failure.
*
* Returns:
* The connector status as defined by enum drm_connector_status.
*/
int drm_connector_helper_detect_from_ddc(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx,
bool force)
{
struct i2c_adapter *ddc = connector->ddc;

if (!ddc)
return connector_status_unknown;

if (drm_probe_ddc(ddc))
return connector_status_connected;

return connector_status_disconnected;
}
EXPORT_SYMBOL(drm_connector_helper_detect_from_ddc);
8 changes: 8 additions & 0 deletions drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,17 @@ static void fsl_dcu_drm_remove(struct platform_device *pdev)
clk_unregister(fsl_dev->pix_clk);
}

static void fsl_dcu_drm_shutdown(struct platform_device *pdev)
{
struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);

drm_atomic_helper_shutdown(fsl_dev->drm);
}

static struct platform_driver fsl_dcu_drm_platform_driver = {
.probe = fsl_dcu_drm_probe,
.remove_new = fsl_dcu_drm_remove,
.shutdown = fsl_dcu_drm_shutdown,
.driver = {
.name = "fsl-dcu",
.pm = &fsl_dcu_drm_pm_ops,
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/hisilicon/hibmc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ config DRM_HISI_HIBMC
tristate "DRM Support for Hisilicon Hibmc"
depends on DRM && PCI && (ARM64 || COMPILE_TEST)
depends on MMU
select DRM_DISPLAY_HELPER
select DRM_DISPLAY_DP_HELPER
select DRM_KMS_HELPER
select DRM_VRAM_HELPER
select DRM_TTM
Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/hisilicon/hibmc/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_i2c.o
hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_i2c.o \
dp/dp_aux.o dp/dp_link.o dp/dp_hw.o dp/dp_serdes.o hibmc_drm_dp.o \
hibmc_drm_debugfs.o

obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc-drm.o
168 changes: 168 additions & 0 deletions drivers/gpu/drm/hisilicon/hibmc/dp/dp_aux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (c) 2024 Hisilicon Limited.

#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/minmax.h>
#include <drm/drm_device.h>
#include <drm/drm_print.h>
#include "dp_comm.h"
#include "dp_reg.h"
#include "dp_hw.h"

#define HIBMC_AUX_CMD_REQ_LEN GENMASK(7, 4)
#define HIBMC_AUX_CMD_ADDR GENMASK(27, 8)
#define HIBMC_AUX_CMD_I2C_ADDR_ONLY BIT(28)
#define HIBMC_BYTES_IN_U32 4
#define HIBMC_AUX_I2C_WRITE_SUCCESS 0x1
#define HIBMC_DP_MIN_PULSE_NUM 0x9
#define BITS_IN_U8 8

static inline void hibmc_dp_aux_reset(struct hibmc_dp_dev *dp)
{
hibmc_dp_reg_write_field(dp, HIBMC_DP_DPTX_RST_CTRL, HIBMC_DP_CFG_AUX_RST_N, 0x0);
usleep_range(10, 15);
hibmc_dp_reg_write_field(dp, HIBMC_DP_DPTX_RST_CTRL, HIBMC_DP_CFG_AUX_RST_N, 0x1);
}

static void hibmc_dp_aux_read_data(struct hibmc_dp_dev *dp, u8 *buf, u8 size)
{
u32 reg_num;
u32 value;
u32 num;
u8 i, j;

reg_num = DIV_ROUND_UP(size, HIBMC_BYTES_IN_U32);
for (i = 0; i < reg_num; i++) {
/* number of bytes read from a single register */
num = min(size - i * HIBMC_BYTES_IN_U32, HIBMC_BYTES_IN_U32);
value = readl(dp->base + HIBMC_DP_AUX_RD_DATA0 + i * HIBMC_BYTES_IN_U32);
/* convert the 32-bit value of the register to the buffer. */
for (j = 0; j < num; j++)
buf[i * HIBMC_BYTES_IN_U32 + j] = value >> (j * BITS_IN_U8);
}
}

static void hibmc_dp_aux_write_data(struct hibmc_dp_dev *dp, u8 *buf, u8 size)
{
u32 reg_num;
u32 value;
u32 num;
u8 i, j;

reg_num = DIV_ROUND_UP(size, HIBMC_BYTES_IN_U32);
for (i = 0; i < reg_num; i++) {
/* number of bytes written to a single register */
num = min_t(u8, size - i * HIBMC_BYTES_IN_U32, HIBMC_BYTES_IN_U32);
value = 0;
/* obtain the 32-bit value written to a single register. */
for (j = 0; j < num; j++)
value |= buf[i * HIBMC_BYTES_IN_U32 + j] << (j * BITS_IN_U8);
/* writing data to a single register */
writel(value, dp->base + HIBMC_DP_AUX_WR_DATA0 + i * HIBMC_BYTES_IN_U32);
}
}

static u32 hibmc_dp_aux_build_cmd(const struct drm_dp_aux_msg *msg)
{
u32 aux_cmd = msg->request;

if (msg->size)
aux_cmd |= FIELD_PREP(HIBMC_AUX_CMD_REQ_LEN, (msg->size - 1));
else
aux_cmd |= FIELD_PREP(HIBMC_AUX_CMD_I2C_ADDR_ONLY, 1);

aux_cmd |= FIELD_PREP(HIBMC_AUX_CMD_ADDR, msg->address);

return aux_cmd;
}

/* ret >= 0, ret is size; ret < 0, ret is err code */
static int hibmc_dp_aux_parse_xfer(struct hibmc_dp_dev *dp, struct drm_dp_aux_msg *msg)
{
u32 buf_data_cnt;
u32 aux_status;

aux_status = readl(dp->base + HIBMC_DP_AUX_STATUS);
msg->reply = FIELD_GET(HIBMC_DP_CFG_AUX_STATUS, aux_status);

if (aux_status & HIBMC_DP_CFG_AUX_TIMEOUT)
return -ETIMEDOUT;

/* only address */
if (!msg->size)
return 0;

if (msg->reply != DP_AUX_NATIVE_REPLY_ACK)
return -EIO;

buf_data_cnt = FIELD_GET(HIBMC_DP_CFG_AUX_READY_DATA_BYTE, aux_status);

switch (msg->request) {
case DP_AUX_NATIVE_WRITE:
return msg->size;
case DP_AUX_I2C_WRITE | DP_AUX_I2C_MOT:
if (buf_data_cnt == HIBMC_AUX_I2C_WRITE_SUCCESS)
return msg->size;
else
return FIELD_GET(HIBMC_DP_CFG_AUX, aux_status);
case DP_AUX_NATIVE_READ:
case DP_AUX_I2C_READ | DP_AUX_I2C_MOT:
buf_data_cnt--;
if (buf_data_cnt != msg->size) {
/* only the successful part of data is read */
return -EBUSY;
}

/* all data is successfully read */
hibmc_dp_aux_read_data(dp, msg->buffer, msg->size);
return msg->size;
default:
return -EINVAL;
}
}

/* ret >= 0 ,ret is size; ret < 0, ret is err code */
static ssize_t hibmc_dp_aux_xfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
{
struct hibmc_dp *dp_priv = container_of(aux, struct hibmc_dp, aux);
struct hibmc_dp_dev *dp = dp_priv->dp_dev;
u32 aux_cmd;
int ret;
u32 val; /* val will be assigned at the beginning of readl_poll_timeout function */

writel(0, dp->base + HIBMC_DP_AUX_WR_DATA0);
writel(0, dp->base + HIBMC_DP_AUX_WR_DATA1);
writel(0, dp->base + HIBMC_DP_AUX_WR_DATA2);
writel(0, dp->base + HIBMC_DP_AUX_WR_DATA3);

hibmc_dp_aux_write_data(dp, msg->buffer, msg->size);

aux_cmd = hibmc_dp_aux_build_cmd(msg);
writel(aux_cmd, dp->base + HIBMC_DP_AUX_CMD_ADDR);

/* enable aux transfer */
hibmc_dp_reg_write_field(dp, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_REQ, 0x1);
ret = readl_poll_timeout(dp->base + HIBMC_DP_AUX_REQ, val,
!(val & HIBMC_DP_CFG_AUX_REQ), 50, 5000);
if (ret) {
hibmc_dp_aux_reset(dp);
return ret;
}

return hibmc_dp_aux_parse_xfer(dp, msg);
}

void hibmc_dp_aux_init(struct hibmc_dp *dp)
{
hibmc_dp_reg_write_field(dp->dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_SYNC_LEN_SEL, 0x0);
hibmc_dp_reg_write_field(dp->dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_TIMER_TIMEOUT, 0x1);
hibmc_dp_reg_write_field(dp->dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_MIN_PULSE_NUM,
HIBMC_DP_MIN_PULSE_NUM);

dp->aux.transfer = hibmc_dp_aux_xfer;
dp->aux.name = "HIBMC DRM dp aux";
dp->aux.drm_dev = dp->drm_dev;
drm_dp_aux_init(&dp->aux);
dp->dp_dev->aux = &dp->aux;
}
Loading