Commit e1f9c849 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'mediatek-drm-next-6.6' of...

Merge tag 'mediatek-drm-next-6.6' of https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux into drm-next

Mediatek DRM Next for Linux 6.6

1. Small mtk-dpi cleanups
2. DisplayPort: support eDP and aux-bus
3. Fix uninitialized symbol
4. Do not check for 0 return after calling platform_get_irq()
5. Convert to platform remove callback returning void
6. Fix coverity issues
7. Fix potential memory leak if vmap() fail
8. Fix void-pointer-to-enum-cast warning
9. Rid W=1 warnings from GPU
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20230813152726.14802-1-chunkuang.hu@kernel.org
parents 57bca71d fb7e600d
......@@ -26,6 +26,7 @@ config DRM_MEDIATEK_DP
select PHY_MTK_DP
select DRM_DISPLAY_HELPER
select DRM_DISPLAY_DP_HELPER
select DRM_DP_AUX_BUS
help
DRM/KMS Display Port driver for MediaTek SoCs.
......
......@@ -235,13 +235,12 @@ static int mtk_cec_probe(struct platform_device *pdev)
return 0;
}
static int mtk_cec_remove(struct platform_device *pdev)
static void mtk_cec_remove(struct platform_device *pdev)
{
struct mtk_cec *cec = platform_get_drvdata(pdev);
mtk_cec_htplg_irq_disable(cec);
clk_disable_unprepare(cec->clk);
return 0;
}
static const struct of_device_id mtk_cec_of_ids[] = {
......@@ -252,7 +251,7 @@ MODULE_DEVICE_TABLE(of, mtk_cec_of_ids);
struct platform_driver mtk_cec_driver = {
.probe = mtk_cec_probe,
.remove = mtk_cec_remove,
.remove_new = mtk_cec_remove,
.driver = {
.name = "mediatek-cec",
.of_match_table = mtk_cec_of_ids,
......
......@@ -25,11 +25,6 @@ struct mtk_disp_aal_data {
bool has_gamma;
};
/**
* struct mtk_disp_aal - DISP_AAL driver structure
* @ddp_comp - structure containing type enum and hardware resources
* @crtc - associated crtc to report irq events to
*/
struct mtk_disp_aal {
struct clk *clk;
void __iomem *regs;
......@@ -139,11 +134,9 @@ static int mtk_disp_aal_probe(struct platform_device *pdev)
return ret;
}
static int mtk_disp_aal_remove(struct platform_device *pdev)
static void mtk_disp_aal_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_disp_aal_component_ops);
return 0;
}
static const struct mtk_disp_aal_data mt8173_aal_driver_data = {
......@@ -160,7 +153,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_aal_driver_dt_match);
struct platform_driver mtk_disp_aal_driver = {
.probe = mtk_disp_aal_probe,
.remove = mtk_disp_aal_remove,
.remove_new = mtk_disp_aal_remove,
.driver = {
.name = "mediatek-disp-aal",
.owner = THIS_MODULE,
......
......@@ -33,11 +33,6 @@ struct mtk_disp_ccorr_data {
u32 matrix_bits;
};
/**
* struct mtk_disp_ccorr - DISP_CCORR driver structure
* @ddp_comp - structure containing type enum and hardware resources
* @crtc - associated crtc to report irq events to
*/
struct mtk_disp_ccorr {
struct clk *clk;
void __iomem *regs;
......@@ -194,11 +189,9 @@ static int mtk_disp_ccorr_probe(struct platform_device *pdev)
return ret;
}
static int mtk_disp_ccorr_remove(struct platform_device *pdev)
static void mtk_disp_ccorr_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_disp_ccorr_component_ops);
return 0;
}
static const struct mtk_disp_ccorr_data mt8183_ccorr_driver_data = {
......@@ -220,7 +213,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_ccorr_driver_dt_match);
struct platform_driver mtk_disp_ccorr_driver = {
.probe = mtk_disp_ccorr_probe,
.remove = mtk_disp_ccorr_remove,
.remove_new = mtk_disp_ccorr_remove,
.driver = {
.name = "mediatek-disp-ccorr",
.owner = THIS_MODULE,
......
......@@ -131,11 +131,9 @@ static int mtk_disp_color_probe(struct platform_device *pdev)
return ret;
}
static int mtk_disp_color_remove(struct platform_device *pdev)
static void mtk_disp_color_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_disp_color_component_ops);
return 0;
}
static const struct mtk_disp_color_data mt2701_color_driver_data = {
......@@ -163,7 +161,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_color_driver_dt_match);
struct platform_driver mtk_disp_color_driver = {
.probe = mtk_disp_color_probe,
.remove = mtk_disp_color_remove,
.remove_new = mtk_disp_color_remove,
.driver = {
.name = "mediatek-disp-color",
.owner = THIS_MODULE,
......
......@@ -182,11 +182,9 @@ static int mtk_disp_gamma_probe(struct platform_device *pdev)
return ret;
}
static int mtk_disp_gamma_remove(struct platform_device *pdev)
static void mtk_disp_gamma_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_disp_gamma_component_ops);
return 0;
}
static const struct mtk_disp_gamma_data mt8173_gamma_driver_data = {
......@@ -208,7 +206,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_gamma_driver_dt_match);
struct platform_driver mtk_disp_gamma_driver = {
.probe = mtk_disp_gamma_probe,
.remove = mtk_disp_gamma_remove,
.remove_new = mtk_disp_gamma_remove,
.driver = {
.name = "mediatek-disp-gamma",
.owner = THIS_MODULE,
......
......@@ -294,11 +294,9 @@ static int mtk_disp_merge_probe(struct platform_device *pdev)
return ret;
}
static int mtk_disp_merge_remove(struct platform_device *pdev)
static void mtk_disp_merge_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_disp_merge_component_ops);
return 0;
}
static const struct of_device_id mtk_disp_merge_driver_dt_match[] = {
......@@ -310,7 +308,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_merge_driver_dt_match);
struct platform_driver mtk_disp_merge_driver = {
.probe = mtk_disp_merge_probe,
.remove = mtk_disp_merge_remove,
.remove_new = mtk_disp_merge_remove,
.driver = {
.name = "mediatek-disp-merge",
.owner = THIS_MODULE,
......
......@@ -561,12 +561,10 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
return ret;
}
static int mtk_disp_ovl_remove(struct platform_device *pdev)
static void mtk_disp_ovl_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_disp_ovl_component_ops);
pm_runtime_disable(&pdev->dev);
return 0;
}
static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
......@@ -658,7 +656,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
struct platform_driver mtk_disp_ovl_driver = {
.probe = mtk_disp_ovl_probe,
.remove = mtk_disp_ovl_remove,
.remove_new = mtk_disp_ovl_remove,
.driver = {
.name = "mediatek-disp-ovl",
.owner = THIS_MODULE,
......
......@@ -427,7 +427,7 @@ static int ovl_adaptor_comp_init(struct device *dev, struct component_match **ma
continue;
}
type = (enum mtk_ovl_adaptor_comp_type)of_id->data;
type = (enum mtk_ovl_adaptor_comp_type)(uintptr_t)of_id->data;
id = ovl_adaptor_comp_get_id(dev, node, type);
if (id < 0) {
dev_warn(dev, "Skipping unknown component %pOF\n",
......
......@@ -379,13 +379,11 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
return ret;
}
static int mtk_disp_rdma_remove(struct platform_device *pdev)
static void mtk_disp_rdma_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_disp_rdma_component_ops);
pm_runtime_disable(&pdev->dev);
return 0;
}
static const struct mtk_disp_rdma_data mt2701_rdma_driver_data = {
......@@ -427,7 +425,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
struct platform_driver mtk_disp_rdma_driver = {
.probe = mtk_disp_rdma_probe,
.remove = mtk_disp_rdma_remove,
.remove_new = mtk_disp_rdma_remove,
.driver = {
.name = "mediatek-disp-rdma",
.owner = THIS_MODULE,
......
......@@ -4,6 +4,7 @@
* Copyright (c) 2022 BayLibre
*/
#include <drm/display/drm_dp_aux_bus.h>
#include <drm/display/drm_dp.h>
#include <drm/display/drm_dp_helper.h>
#include <drm/drm_atomic_helper.h>
......@@ -100,6 +101,7 @@ struct mtk_dp_efuse_fmt {
struct mtk_dp {
bool enabled;
bool need_debounce;
int irq;
u8 max_lanes;
u8 max_linkrate;
u8 rx_cap[DP_RECEIVER_CAP_SIZE];
......@@ -847,7 +849,7 @@ static int mtk_dp_aux_do_transfer(struct mtk_dp *mtk_dp, bool is_read, u8 cmd,
u32 phy_status = mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3628) &
AUX_RX_PHY_STATE_AUX_TX_P0_MASK;
if (phy_status != AUX_RX_PHY_STATE_AUX_TX_P0_RX_IDLE) {
drm_err(mtk_dp->drm_dev,
dev_err(mtk_dp->dev,
"AUX Rx Aux hang, need SW reset\n");
return -EIO;
}
......@@ -1009,6 +1011,11 @@ static void mtk_dp_initialize_aux_settings(struct mtk_dp *mtk_dp)
mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_37C8,
MTK_ATOP_EN_AUX_TX_P0,
MTK_ATOP_EN_AUX_TX_P0);
/* Set complete reply mode for AUX */
mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3690,
RX_REPLY_COMPLETE_MODE_AUX_TX_P0,
RX_REPLY_COMPLETE_MODE_AUX_TX_P0);
}
static void mtk_dp_initialize_digital_settings(struct mtk_dp *mtk_dp)
......@@ -1251,6 +1258,29 @@ static void mtk_dp_audio_mute(struct mtk_dp *mtk_dp, bool mute)
val[2], AU_TS_CFG_DP_ENC0_P0_MASK);
}
static void mtk_dp_aux_panel_poweron(struct mtk_dp *mtk_dp, bool pwron)
{
if (pwron) {
/* power on aux */
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
DP_PWR_STATE_BANDGAP_TPLL_LANE,
DP_PWR_STATE_MASK);
/* power on panel */
drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
usleep_range(2000, 5000);
} else {
/* power off panel */
drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
usleep_range(2000, 3000);
/* power off aux */
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
DP_PWR_STATE_BANDGAP_TPLL,
DP_PWR_STATE_MASK);
}
}
static void mtk_dp_power_enable(struct mtk_dp *mtk_dp)
{
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_RESET_AND_PROBE,
......@@ -1284,9 +1314,11 @@ static void mtk_dp_power_disable(struct mtk_dp *mtk_dp)
static void mtk_dp_initialize_priv_data(struct mtk_dp *mtk_dp)
{
bool plugged_in = (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP);
mtk_dp->train_info.link_rate = DP_LINK_BW_5_4;
mtk_dp->train_info.lane_count = mtk_dp->max_lanes;
mtk_dp->train_info.cable_plugged_in = false;
mtk_dp->train_info.cable_plugged_in = plugged_in;
mtk_dp->info.format = DP_PIXELFORMAT_RGB;
memset(&mtk_dp->info.vm, 0, sizeof(struct videomode));
......@@ -1588,7 +1620,19 @@ static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp)
u8 val;
ssize_t ret;
drm_dp_read_dpcd_caps(&mtk_dp->aux, mtk_dp->rx_cap);
/*
* If we're eDP and capabilities were already parsed we can skip
* reading again because eDP panels aren't hotpluggable hence the
* caps and training information won't ever change in a boot life
*/
if (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP &&
mtk_dp->rx_cap[DP_MAX_LINK_RATE] &&
mtk_dp->train_info.sink_ssc)
return 0;
ret = drm_dp_read_dpcd_caps(&mtk_dp->aux, mtk_dp->rx_cap);
if (ret < 0)
return ret;
if (drm_dp_tps4_supported(mtk_dp->rx_cap))
mtk_dp->train_info.channel_eq_pattern = DP_TRAINING_PATTERN_4;
......@@ -1615,10 +1659,13 @@ static int mtk_dp_parse_capabilities(struct mtk_dp *mtk_dp)
return ret == 0 ? -EIO : ret;
}
if (val)
drm_dp_dpcd_writeb(&mtk_dp->aux,
if (val) {
ret = drm_dp_dpcd_writeb(&mtk_dp->aux,
DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0,
val);
if (ret < 0)
return ret;
}
}
return 0;
......@@ -1798,10 +1845,6 @@ static void mtk_dp_init_port(struct mtk_dp *mtk_dp)
mtk_dp_initialize_settings(mtk_dp);
mtk_dp_initialize_aux_settings(mtk_dp);
mtk_dp_initialize_digital_settings(mtk_dp);
mtk_dp_update_bits(mtk_dp, MTK_DP_AUX_P0_3690,
RX_REPLY_COMPLETE_MODE_AUX_TX_P0,
RX_REPLY_COMPLETE_MODE_AUX_TX_P0);
mtk_dp_initialize_hpd_detect_settings(mtk_dp);
mtk_dp_digital_sw_reset(mtk_dp);
......@@ -1877,6 +1920,31 @@ static irqreturn_t mtk_dp_hpd_event(int hpd, void *dev)
return IRQ_WAKE_THREAD;
}
static int mtk_dp_wait_hpd_asserted(struct drm_dp_aux *mtk_aux, unsigned long wait_us)
{
struct mtk_dp *mtk_dp = container_of(mtk_aux, struct mtk_dp, aux);
u32 val;
int ret;
ret = regmap_read_poll_timeout(mtk_dp->regs, MTK_DP_TRANS_P0_3414,
val, !!(val & HPD_DB_DP_TRANS_P0_MASK),
wait_us / 100, wait_us);
if (ret) {
mtk_dp->train_info.cable_plugged_in = false;
return ret;
}
mtk_dp->train_info.cable_plugged_in = true;
ret = mtk_dp_parse_capabilities(mtk_dp);
if (ret) {
drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n");
return ret;
}
return 0;
}
static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp,
struct platform_device *pdev)
{
......@@ -1918,6 +1986,9 @@ static int mtk_dp_dt_parse(struct mtk_dp *mtk_dp,
static void mtk_dp_update_plugged_status(struct mtk_dp *mtk_dp)
{
if (!mtk_dp->data->audio_supported || !mtk_dp->audio_enable)
return;
mutex_lock(&mtk_dp->update_plugged_status_lock);
if (mtk_dp->plugged_cb && mtk_dp->codec_dev)
mtk_dp->plugged_cb(mtk_dp->codec_dev,
......@@ -1936,16 +2007,9 @@ static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge)
if (!mtk_dp->train_info.cable_plugged_in)
return ret;
if (!enabled) {
/* power on aux */
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
DP_PWR_STATE_BANDGAP_TPLL_LANE,
DP_PWR_STATE_MASK);
if (!enabled)
mtk_dp_aux_panel_poweron(mtk_dp, true);
/* power on panel */
drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
usleep_range(2000, 5000);
}
/*
* Some dongles still source HPD when they do not connect to any
* sink device. To avoid this, we need to read the sink count
......@@ -1957,16 +2021,8 @@ static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge)
if (DP_GET_SINK_COUNT(sink_count))
ret = connector_status_connected;
if (!enabled) {
/* power off panel */
drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
usleep_range(2000, 3000);
/* power off aux */
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
DP_PWR_STATE_BANDGAP_TPLL,
DP_PWR_STATE_MASK);
}
if (!enabled)
mtk_dp_aux_panel_poweron(mtk_dp, false);
return ret;
}
......@@ -1982,15 +2038,7 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge,
if (!enabled) {
drm_atomic_bridge_chain_pre_enable(bridge, connector->state->state);
/* power on aux */
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
DP_PWR_STATE_BANDGAP_TPLL_LANE,
DP_PWR_STATE_MASK);
/* power on panel */
drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
usleep_range(2000, 5000);
mtk_dp_aux_panel_poweron(mtk_dp, true);
}
new_edid = drm_get_edid(connector, &mtk_dp->aux.ddc);
......@@ -2010,15 +2058,7 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge,
}
if (!enabled) {
/* power off panel */
drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
usleep_range(2000, 3000);
/* power off aux */
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
DP_PWR_STATE_BANDGAP_TPLL,
DP_PWR_STATE_MASK);
mtk_dp_aux_panel_poweron(mtk_dp, false);
drm_atomic_bridge_chain_post_disable(bridge, connector->state->state);
}
......@@ -2028,15 +2068,14 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge,
static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux,
struct drm_dp_aux_msg *msg)
{
struct mtk_dp *mtk_dp;
struct mtk_dp *mtk_dp = container_of(mtk_aux, struct mtk_dp, aux);
bool is_read;
u8 request;
size_t accessed_bytes = 0;
int ret;
mtk_dp = container_of(mtk_aux, struct mtk_dp, aux);
if (!mtk_dp->train_info.cable_plugged_in) {
if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP &&
!mtk_dp->train_info.cable_plugged_in) {
ret = -EAGAIN;
goto err;
}
......@@ -2057,7 +2096,7 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux,
is_read = true;
break;
default:
drm_err(mtk_aux->drm_dev, "invalid aux cmd = %d\n",
dev_err(mtk_dp->dev, "invalid aux cmd = %d\n",
msg->request);
ret = -EINVAL;
goto err;
......@@ -2073,7 +2112,7 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux,
to_access, &msg->reply);
if (ret) {
drm_info(mtk_dp->drm_dev,
dev_info(mtk_dp->dev,
"Failed to do AUX transfer: %d\n", ret);
goto err;
}
......@@ -2143,7 +2182,11 @@ static int mtk_dp_bridge_attach(struct drm_bridge *bridge,
mtk_dp->drm_dev = bridge->dev;
if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP) {
irq_clear_status_flags(mtk_dp->irq, IRQ_NOAUTOEN);
enable_irq(mtk_dp->irq);
mtk_dp_hwirq_enable(mtk_dp, true);
}
return 0;
......@@ -2158,7 +2201,10 @@ static void mtk_dp_bridge_detach(struct drm_bridge *bridge)
{
struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge);
if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP) {
mtk_dp_hwirq_enable(mtk_dp, false);
disable_irq(mtk_dp->irq);
}
mtk_dp->drm_dev = NULL;
mtk_dp_poweroff(mtk_dp);
drm_dp_aux_unregister(&mtk_dp->aux);
......@@ -2178,15 +2224,7 @@ static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge,
return;
}
/* power on aux */
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
DP_PWR_STATE_BANDGAP_TPLL_LANE,
DP_PWR_STATE_MASK);
if (mtk_dp->train_info.cable_plugged_in) {
drm_dp_dpcd_writeb(&mtk_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
usleep_range(2000, 5000);
}
mtk_dp_aux_panel_poweron(mtk_dp, true);
/* Training */
ret = mtk_dp_training(mtk_dp);
......@@ -2481,11 +2519,62 @@ static int mtk_dp_register_audio_driver(struct device *dev)
return PTR_ERR_OR_ZERO(mtk_dp->audio_pdev);
}
static int mtk_dp_register_phy(struct mtk_dp *mtk_dp)
{
struct device *dev = mtk_dp->dev;
mtk_dp->phy_dev = platform_device_register_data(dev, "mediatek-dp-phy",
PLATFORM_DEVID_AUTO,
&mtk_dp->regs,
sizeof(struct regmap *));
if (IS_ERR(mtk_dp->phy_dev))
return dev_err_probe(dev, PTR_ERR(mtk_dp->phy_dev),
"Failed to create device mediatek-dp-phy\n");
mtk_dp_get_calibration_data(mtk_dp);
mtk_dp->phy = devm_phy_get(&mtk_dp->phy_dev->dev, "dp");
if (IS_ERR(mtk_dp->phy)) {
platform_device_unregister(mtk_dp->phy_dev);
return dev_err_probe(dev, PTR_ERR(mtk_dp->phy), "Failed to get phy\n");
}
return 0;
}
static int mtk_dp_edp_link_panel(struct drm_dp_aux *mtk_aux)
{
struct mtk_dp *mtk_dp = container_of(mtk_aux, struct mtk_dp, aux);
struct device *dev = mtk_aux->dev;
int ret;
mtk_dp->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
/* Power off the DP and AUX: either detection is done, or no panel present */
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
DP_PWR_STATE_BANDGAP_TPLL,
DP_PWR_STATE_MASK);
mtk_dp_power_disable(mtk_dp);
if (IS_ERR(mtk_dp->next_bridge)) {
ret = PTR_ERR(mtk_dp->next_bridge);
mtk_dp->next_bridge = NULL;
return ret;
}
/* For eDP, we add the bridge only if the panel was found */
ret = devm_drm_bridge_add(dev, &mtk_dp->bridge);
if (ret)
return ret;
return 0;
}
static int mtk_dp_probe(struct platform_device *pdev)
{
struct mtk_dp *mtk_dp;
struct device *dev = &pdev->dev;
int ret, irq_num;
int ret;
mtk_dp = devm_kzalloc(dev, sizeof(*mtk_dp), GFP_KERNEL);
if (!mtk_dp)
......@@ -2494,30 +2583,27 @@ static int mtk_dp_probe(struct platform_device *pdev)
mtk_dp->dev = dev;
mtk_dp->data = (struct mtk_dp_data *)of_device_get_match_data(dev);
irq_num = platform_get_irq(pdev, 0);
if (irq_num < 0)
return dev_err_probe(dev, irq_num,
"failed to request dp irq resource\n");
mtk_dp->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
if (IS_ERR(mtk_dp->next_bridge) &&
PTR_ERR(mtk_dp->next_bridge) == -ENODEV)
mtk_dp->next_bridge = NULL;
else if (IS_ERR(mtk_dp->next_bridge))
return dev_err_probe(dev, PTR_ERR(mtk_dp->next_bridge),
"Failed to get bridge\n");
ret = mtk_dp_dt_parse(mtk_dp, pdev);
if (ret)
return dev_err_probe(dev, ret, "Failed to parse dt\n");
drm_dp_aux_init(&mtk_dp->aux);
mtk_dp->aux.name = "aux_mtk_dp";
mtk_dp->aux.transfer = mtk_dp_aux_transfer;
/*
* Request the interrupt and install service routine only if we are
* on full DisplayPort.
* For eDP, polling the HPD instead is more convenient because we
* don't expect any (un)plug events during runtime, hence we can
* avoid some locking.
*/
if (mtk_dp->data->bridge_type != DRM_MODE_CONNECTOR_eDP) {
mtk_dp->irq = platform_get_irq(pdev, 0);
if (mtk_dp->irq < 0)
return dev_err_probe(dev, mtk_dp->irq,
"failed to request dp irq resource\n");
spin_lock_init(&mtk_dp->irq_thread_lock);
ret = devm_request_threaded_irq(dev, irq_num, mtk_dp_hpd_event,
irq_set_status_flags(mtk_dp->irq, IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(dev, mtk_dp->irq, mtk_dp_hpd_event,
mtk_dp_hpd_event_thread,
IRQ_TYPE_LEVEL_HIGH, dev_name(dev),
mtk_dp);
......@@ -2525,11 +2611,21 @@ static int mtk_dp_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret,
"failed to request mediatek dptx irq\n");
mutex_init(&mtk_dp->update_plugged_status_lock);
mtk_dp->need_debounce = true;
timer_setup(&mtk_dp->debounce_timer, mtk_dp_debounce_timer, 0);
}
mtk_dp->aux.name = "aux_mtk_dp";
mtk_dp->aux.dev = dev;
mtk_dp->aux.transfer = mtk_dp_aux_transfer;
mtk_dp->aux.wait_hpd_asserted = mtk_dp_wait_hpd_asserted;
drm_dp_aux_init(&mtk_dp->aux);
platform_set_drvdata(pdev, mtk_dp);
if (mtk_dp->data->audio_supported) {
mutex_init(&mtk_dp->update_plugged_status_lock);
ret = mtk_dp_register_audio_driver(dev);
if (ret) {
dev_err(dev, "Failed to register audio driver: %d\n",
......@@ -2538,35 +2634,59 @@ static int mtk_dp_probe(struct platform_device *pdev)
}
}
mtk_dp->phy_dev = platform_device_register_data(dev, "mediatek-dp-phy",
PLATFORM_DEVID_AUTO,
&mtk_dp->regs,
sizeof(struct regmap *));
if (IS_ERR(mtk_dp->phy_dev))
return dev_err_probe(dev, PTR_ERR(mtk_dp->phy_dev),
"Failed to create device mediatek-dp-phy\n");
mtk_dp_get_calibration_data(mtk_dp);
mtk_dp->phy = devm_phy_get(&mtk_dp->phy_dev->dev, "dp");
if (IS_ERR(mtk_dp->phy)) {
platform_device_unregister(mtk_dp->phy_dev);
return dev_err_probe(dev, PTR_ERR(mtk_dp->phy),
"Failed to get phy\n");
}
ret = mtk_dp_register_phy(mtk_dp);
if (ret)
return ret;
mtk_dp->bridge.funcs = &mtk_dp_bridge_funcs;
mtk_dp->bridge.of_node = dev->of_node;
mtk_dp->bridge.ops =
DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
mtk_dp->bridge.type = mtk_dp->data->bridge_type;
drm_bridge_add(&mtk_dp->bridge);
if (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP) {
/*
* Set the data lanes to idle in case the bootloader didn't
* properly close the eDP port to avoid stalls and then
* reinitialize, reset and power on the AUX block.
*/
mtk_dp_set_idle_pattern(mtk_dp, true);
mtk_dp_initialize_aux_settings(mtk_dp);
mtk_dp_power_enable(mtk_dp);
/* Disable HW interrupts: we don't need any for eDP */
mtk_dp_hwirq_enable(mtk_dp, false);
mtk_dp->need_debounce = true;
timer_setup(&mtk_dp->debounce_timer, mtk_dp_debounce_timer, 0);
/*
* Power on the AUX to allow reading the EDID from aux-bus:
* please note that it is necessary to call power off in the
* .done_probing() callback (mtk_dp_edp_link_panel), as only
* there we can safely assume that we finished reading EDID.
*/
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
DP_PWR_STATE_BANDGAP_TPLL_LANE,
DP_PWR_STATE_MASK);
ret = devm_of_dp_aux_populate_bus(&mtk_dp->aux, mtk_dp_edp_link_panel);
if (ret) {
/* -ENODEV this means that the panel is not on the aux-bus */
if (ret == -ENODEV) {
ret = mtk_dp_edp_link_panel(&mtk_dp->aux);
if (ret)
return ret;
} else {
mtk_dp_update_bits(mtk_dp, MTK_DP_TOP_PWR_STATE,
DP_PWR_STATE_BANDGAP_TPLL,
DP_PWR_STATE_MASK);
mtk_dp_power_disable(mtk_dp);
return ret;
}
}
} else {
mtk_dp->bridge.ops = DRM_BRIDGE_OP_DETECT |
DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
ret = devm_drm_bridge_add(dev, &mtk_dp->bridge);
if (ret)
return dev_err_probe(dev, ret, "Failed to add bridge\n");
}
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
......@@ -2574,19 +2694,17 @@ static int mtk_dp_probe(struct platform_device *pdev)
return 0;
}
static int mtk_dp_remove(struct platform_device *pdev)
static void mtk_dp_remove(struct platform_device *pdev)
{
struct mtk_dp *mtk_dp = platform_get_drvdata(pdev);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
if (mtk_dp->data->bridge_type != DRM_MODE_CONNECTOR_eDP)
del_timer_sync(&mtk_dp->debounce_timer);
drm_bridge_remove(&mtk_dp->bridge);
platform_device_unregister(mtk_dp->phy_dev);
if (mtk_dp->audio_pdev)
platform_device_unregister(mtk_dp->audio_pdev);
return 0;
}
#ifdef CONFIG_PM_SLEEP
......@@ -2595,6 +2713,7 @@ static int mtk_dp_suspend(struct device *dev)
struct mtk_dp *mtk_dp = dev_get_drvdata(dev);
mtk_dp_power_disable(mtk_dp);
if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP)
mtk_dp_hwirq_enable(mtk_dp, false);
pm_runtime_put_sync(dev);
......@@ -2607,6 +2726,7 @@ static int mtk_dp_resume(struct device *dev)
pm_runtime_get_sync(dev);
mtk_dp_init_port(mtk_dp);
if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP)
mtk_dp_hwirq_enable(mtk_dp, true);
mtk_dp_power_enable(mtk_dp);
......@@ -2645,7 +2765,7 @@ MODULE_DEVICE_TABLE(of, mtk_dp_of_match);
static struct platform_driver mtk_dp_driver = {
.probe = mtk_dp_probe,
.remove = mtk_dp_remove,
.remove_new = mtk_dp_remove,
.driver = {
.name = "mediatek-drm-dp",
.of_match_table = mtk_dp_of_match,
......
......@@ -1006,7 +1006,6 @@ static int mtk_dpi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mtk_dpi *dpi;
struct resource *mem;
int ret;
dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);
......@@ -1037,49 +1036,34 @@ static int mtk_dpi_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "Cannot find pinctrl active!\n");
}
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dpi->regs = devm_ioremap_resource(dev, mem);
if (IS_ERR(dpi->regs)) {
ret = PTR_ERR(dpi->regs);
dev_err(dev, "Failed to ioremap mem resource: %d\n", ret);
return ret;
}
dpi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dpi->regs))
return dev_err_probe(dev, PTR_ERR(dpi->regs),
"Failed to ioremap mem resource\n");
dpi->engine_clk = devm_clk_get(dev, "engine");
if (IS_ERR(dpi->engine_clk)) {
ret = PTR_ERR(dpi->engine_clk);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get engine clock: %d\n", ret);
return ret;
}
if (IS_ERR(dpi->engine_clk))
return dev_err_probe(dev, PTR_ERR(dpi->engine_clk),
"Failed to get engine clock\n");
dpi->pixel_clk = devm_clk_get(dev, "pixel");
if (IS_ERR(dpi->pixel_clk)) {
ret = PTR_ERR(dpi->pixel_clk);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get pixel clock: %d\n", ret);
return ret;
}
if (IS_ERR(dpi->pixel_clk))
return dev_err_probe(dev, PTR_ERR(dpi->pixel_clk),
"Failed to get pixel clock\n");
dpi->tvd_clk = devm_clk_get(dev, "pll");
if (IS_ERR(dpi->tvd_clk)) {
ret = PTR_ERR(dpi->tvd_clk);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get tvdpll clock: %d\n", ret);
return ret;
}
if (IS_ERR(dpi->tvd_clk))
return dev_err_probe(dev, PTR_ERR(dpi->tvd_clk),
"Failed to get tvdpll clock\n");
dpi->irq = platform_get_irq(pdev, 0);
if (dpi->irq <= 0)
return -EINVAL;
if (dpi->irq < 0)
return dpi->irq;
ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
NULL, &dpi->next_bridge);
if (ret)
return ret;
dpi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
if (IS_ERR(dpi->next_bridge))
return dev_err_probe(dev, PTR_ERR(dpi->next_bridge),
"Failed to get bridge\n");
dev_info(dev, "Found bridge node: %pOF\n", dpi->next_bridge->of_node);
......@@ -1089,57 +1073,37 @@ static int mtk_dpi_probe(struct platform_device *pdev)
dpi->bridge.of_node = dev->of_node;
dpi->bridge.type = DRM_MODE_CONNECTOR_DPI;
drm_bridge_add(&dpi->bridge);
ret = devm_drm_bridge_add(dev, &dpi->bridge);
if (ret)
return ret;
ret = component_add(dev, &mtk_dpi_component_ops);
if (ret) {
drm_bridge_remove(&dpi->bridge);
dev_err(dev, "Failed to add component: %d\n", ret);
return ret;
}
if (ret)
return dev_err_probe(dev, ret, "Failed to add component.\n");
return 0;
}
static int mtk_dpi_remove(struct platform_device *pdev)
static void mtk_dpi_remove(struct platform_device *pdev)
{
struct mtk_dpi *dpi = platform_get_drvdata(pdev);
component_del(&pdev->dev, &mtk_dpi_component_ops);
drm_bridge_remove(&dpi->bridge);
return 0;
}
static const struct of_device_id mtk_dpi_of_ids[] = {
{ .compatible = "mediatek,mt2701-dpi",
.data = &mt2701_conf,
},
{ .compatible = "mediatek,mt8173-dpi",
.data = &mt8173_conf,
},
{ .compatible = "mediatek,mt8183-dpi",
.data = &mt8183_conf,
},
{ .compatible = "mediatek,mt8186-dpi",
.data = &mt8186_conf,
},
{ .compatible = "mediatek,mt8188-dp-intf",
.data = &mt8188_dpintf_conf,
},
{ .compatible = "mediatek,mt8192-dpi",
.data = &mt8192_conf,
},
{ .compatible = "mediatek,mt8195-dp-intf",
.data = &mt8195_dpintf_conf,
},
{ },
{ .compatible = "mediatek,mt2701-dpi", .data = &mt2701_conf },
{ .compatible = "mediatek,mt8173-dpi", .data = &mt8173_conf },
{ .compatible = "mediatek,mt8183-dpi", .data = &mt8183_conf },
{ .compatible = "mediatek,mt8186-dpi", .data = &mt8186_conf },
{ .compatible = "mediatek,mt8188-dp-intf", .data = &mt8188_dpintf_conf },
{ .compatible = "mediatek,mt8192-dpi", .data = &mt8192_conf },
{ .compatible = "mediatek,mt8195-dp-intf", .data = &mt8195_dpintf_conf },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, mtk_dpi_of_ids);
struct platform_driver mtk_dpi_driver = {
.probe = mtk_dpi_probe,
.remove = mtk_dpi_remove,
.remove_new = mtk_dpi_remove,
.driver = {
.name = "mediatek-dpi",
.of_match_table = mtk_dpi_of_ids,
......
......@@ -117,10 +117,9 @@ static int mtk_drm_cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *
dma_addr_t dma_addr;
pkt->va_base = kzalloc(size, GFP_KERNEL);
if (!pkt->va_base) {
kfree(pkt);
if (!pkt->va_base)
return -ENOMEM;
}
pkt->buf_size = size;
pkt->cl = (void *)client;
......@@ -130,7 +129,6 @@ static int mtk_drm_cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *
if (dma_mapping_error(dev, dma_addr)) {
dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size);
kfree(pkt->va_base);
kfree(pkt);
return -ENOMEM;
}
......@@ -146,7 +144,6 @@ static void mtk_drm_cmdq_pkt_destroy(struct cmdq_pkt *pkt)
dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size,
DMA_TO_DEVICE);
kfree(pkt->va_base);
kfree(pkt);
}
#endif
......
......@@ -563,14 +563,15 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
/* Not all drm components have a DTS device node, such as ovl_adaptor,
* which is the drm bring up sub driver
*/
if (node) {
if (!node)
return 0;
comp_pdev = of_find_device_by_node(node);
if (!comp_pdev) {
DRM_INFO("Waiting for device %s\n", node->full_name);
return -EPROBE_DEFER;
}
comp->dev = &comp_pdev->dev;
}
if (type == MTK_DISP_AAL ||
type == MTK_DISP_BLS ||
......@@ -580,7 +581,6 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
type == MTK_DISP_MERGE ||
type == MTK_DISP_OVL ||
type == MTK_DISP_OVL_2L ||
type == MTK_DISP_OVL_ADAPTOR ||
type == MTK_DISP_PWM ||
type == MTK_DISP_RDMA ||
type == MTK_DPI ||
......
......@@ -355,7 +355,7 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
const struct of_device_id *of_id;
struct device_node *node;
struct device *drm_dev;
int cnt = 0;
unsigned int cnt = 0;
int i, j;
for_each_child_of_node(phandle->parent, node) {
......@@ -376,6 +376,9 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
all_drm_priv[cnt] = dev_get_drvdata(drm_dev);
if (all_drm_priv[cnt] && all_drm_priv[cnt]->mtk_drm_bound)
cnt++;
if (cnt == MAX_CRTC)
break;
}
if (drm_priv->data->mmsys_dev_num == cnt) {
......@@ -827,7 +830,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
continue;
}
comp_type = (enum mtk_ddp_comp_type)of_id->data;
comp_type = (enum mtk_ddp_comp_type)(uintptr_t)of_id->data;
if (comp_type == MTK_DISP_MUTEX) {
int id;
......@@ -907,7 +910,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
return ret;
}
static int mtk_drm_remove(struct platform_device *pdev)
static void mtk_drm_remove(struct platform_device *pdev)
{
struct mtk_drm_private *private = platform_get_drvdata(pdev);
int i;
......@@ -917,8 +920,6 @@ static int mtk_drm_remove(struct platform_device *pdev)
of_node_put(private->mutex_node);
for (i = 0; i < DDP_COMPONENT_DRM_ID_MAX; i++)
of_node_put(private->comp_node[i]);
return 0;
}
static int mtk_drm_sys_prepare(struct device *dev)
......@@ -951,7 +952,7 @@ static const struct dev_pm_ops mtk_drm_pm_ops = {
static struct platform_driver mtk_drm_platform_driver = {
.probe = mtk_drm_probe,
.remove = mtk_drm_remove,
.remove_new = mtk_drm_remove,
.driver = {
.name = "mediatek-drm",
.pm = &mtk_drm_pm_ops,
......
......@@ -247,7 +247,11 @@ int mtk_drm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP,
pgprot_writecombine(PAGE_KERNEL));
if (!mtk_gem->kvaddr) {
kfree(sgt);
kfree(mtk_gem->pages);
return -ENOMEM;
}
out:
kfree(sgt);
iosys_map_set_vaddr(map, mtk_gem->kvaddr);
......
......@@ -122,11 +122,7 @@ static int mtk_plane_atomic_async_check(struct drm_plane *plane,
if (ret)
return ret;
if (state)
crtc_state = drm_atomic_get_existing_crtc_state(state,
new_plane_state->crtc);
else /* Special case for asynchronous cursor updates. */
crtc_state = new_plane_state->crtc->state;
crtc_state = drm_atomic_get_existing_crtc_state(state, new_plane_state->crtc);
return drm_atomic_helper_check_plane_state(plane->state, crtc_state,
DRM_PLANE_NO_SCALING,
......
......@@ -1178,14 +1178,12 @@ static int mtk_dsi_probe(struct platform_device *pdev)
return ret;
}
static int mtk_dsi_remove(struct platform_device *pdev)
static void mtk_dsi_remove(struct platform_device *pdev)
{
struct mtk_dsi *dsi = platform_get_drvdata(pdev);
mtk_output_dsi_disable(dsi);
mipi_dsi_host_unregister(&dsi->host);
return 0;
}
static const struct mtk_dsi_driver_data mt8173_dsi_driver_data = {
......@@ -1223,7 +1221,7 @@ MODULE_DEVICE_TABLE(of, mtk_dsi_of_match);
struct platform_driver mtk_dsi_driver = {
.probe = mtk_dsi_probe,
.remove = mtk_dsi_remove,
.remove_new = mtk_dsi_remove,
.driver = {
.name = "mtk-dsi",
.of_match_table = mtk_dsi_of_match,
......
......@@ -1746,13 +1746,12 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
return ret;
}
static int mtk_drm_hdmi_remove(struct platform_device *pdev)
static void mtk_drm_hdmi_remove(struct platform_device *pdev)
{
struct mtk_hdmi *hdmi = platform_get_drvdata(pdev);
drm_bridge_remove(&hdmi->bridge);
mtk_hdmi_clk_disable_audio(hdmi);
return 0;
}
#ifdef CONFIG_PM_SLEEP
......@@ -1806,7 +1805,7 @@ MODULE_DEVICE_TABLE(of, mtk_drm_hdmi_of_ids);
static struct platform_driver mtk_hdmi_driver = {
.probe = mtk_drm_hdmi_probe,
.remove = mtk_drm_hdmi_remove,
.remove_new = mtk_drm_hdmi_remove,
.driver = {
.name = "mediatek-drm-hdmi",
.of_match_table = mtk_drm_hdmi_of_ids,
......
......@@ -324,14 +324,12 @@ static int mtk_hdmi_ddc_probe(struct platform_device *pdev)
return ret;
}
static int mtk_hdmi_ddc_remove(struct platform_device *pdev)
static void mtk_hdmi_ddc_remove(struct platform_device *pdev)
{
struct mtk_hdmi_ddc *ddc = platform_get_drvdata(pdev);
i2c_del_adapter(&ddc->adap);
clk_disable_unprepare(ddc->clk);
return 0;
}
static const struct of_device_id mtk_hdmi_ddc_match[] = {
......@@ -342,7 +340,7 @@ MODULE_DEVICE_TABLE(of, mtk_hdmi_ddc_match);
struct platform_driver mtk_hdmi_ddc_driver = {
.probe = mtk_hdmi_ddc_probe,
.remove = mtk_hdmi_ddc_remove,
.remove_new = mtk_hdmi_ddc_remove,
.driver = {
.name = "mediatek-hdmi-ddc",
.of_match_table = mtk_hdmi_ddc_match,
......
......@@ -314,11 +314,10 @@ static int mtk_mdp_rdma_probe(struct platform_device *pdev)
return ret;
}
static int mtk_mdp_rdma_remove(struct platform_device *pdev)
static void mtk_mdp_rdma_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_mdp_rdma_component_ops);
pm_runtime_disable(&pdev->dev);
return 0;
}
static const struct of_device_id mtk_mdp_rdma_driver_dt_match[] = {
......@@ -329,7 +328,7 @@ MODULE_DEVICE_TABLE(of, mtk_mdp_rdma_driver_dt_match);
struct platform_driver mtk_mdp_rdma_driver = {
.probe = mtk_mdp_rdma_probe,
.remove = mtk_mdp_rdma_remove,
.remove_new = mtk_mdp_rdma_remove,
.driver = {
.name = "mediatek-mdp-rdma",
.owner = THIS_MODULE,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment