[PATCH 1/7] drm/sun4i: dw-hdmi: Deinit PHY in fail path

2023-09-24 Thread Jernej Skrabec
Commit 9bf3797796f5 ("drm/sun4i: dw-hdmi: Make HDMI PHY into a platform
device") removed code for PHY deinitialization in fail path.

Add it back.

Fixes: 9bf3797796f5 ("drm/sun4i: dw-hdmi: Make HDMI PHY into a platform device")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 4727dfaa8fb9..0b647b030b15 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -203,6 +203,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
 
 cleanup_encoder:
drm_encoder_cleanup(encoder);
+   sun8i_hdmi_phy_deinit(hdmi->phy);
 err_disable_clk_tmds:
clk_disable_unprepare(hdmi->clk_tmds);
 err_assert_ctrl_reset:
-- 
2.42.0



[PATCH 4/7] drm/sun4i: Don't show error for deferred probes.

2023-09-24 Thread Jernej Skrabec
Drivers probing in display pipeline can be deferred for many reasons.
Don't print error for such cases.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun4i_drv.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c 
b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 6a8dfc022d3c..b4816a1b0be3 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -88,7 +88,8 @@ static int sun4i_drv_bind(struct device *dev)
 
ret = component_bind_all(drm->dev, drm);
if (ret) {
-   dev_err(drm->dev, "Couldn't bind all pipelines components\n");
+   dev_err_probe(drm->dev, ret,
+ "Couldn't bind all pipelines components\n");
goto cleanup_mode_config;
}
 
-- 
2.42.0



[PATCH 5/7] drm/sun4i: dw-hdmi: Split driver registration

2023-09-24 Thread Jernej Skrabec
There is no reason to register two drivers in same place. Using macro
lowers amount of boilerplate code.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c  | 27 +-
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |  2 --
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c |  3 ++-
 3 files changed, 3 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 93831cdf1917..d93e8ff71aae 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -378,32 +378,7 @@ static struct platform_driver sun8i_dw_hdmi_pltfm_driver = 
{
.of_match_table = sun8i_dw_hdmi_dt_ids,
},
 };
-
-static int __init sun8i_dw_hdmi_init(void)
-{
-   int ret;
-
-   ret = platform_driver_register(_dw_hdmi_pltfm_driver);
-   if (ret)
-   return ret;
-
-   ret = platform_driver_register(_hdmi_phy_driver);
-   if (ret) {
-   platform_driver_unregister(_dw_hdmi_pltfm_driver);
-   return ret;
-   }
-
-   return ret;
-}
-
-static void __exit sun8i_dw_hdmi_exit(void)
-{
-   platform_driver_unregister(_dw_hdmi_pltfm_driver);
-   platform_driver_unregister(_hdmi_phy_driver);
-}
-
-module_init(sun8i_dw_hdmi_init);
-module_exit(sun8i_dw_hdmi_exit);
+module_platform_driver(sun8i_dw_hdmi_pltfm_driver);
 
 MODULE_AUTHOR("Jernej Skrabec ");
 MODULE_DESCRIPTION("Allwinner DW HDMI bridge");
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 18ffc1b4841f..21e010deeb48 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -194,8 +194,6 @@ struct sun8i_dw_hdmi {
struct reset_control*rst_ctrl;
 };
 
-extern struct platform_driver sun8i_hdmi_phy_driver;
-
 static inline struct sun8i_dw_hdmi *
 encoder_to_sun8i_dw_hdmi(struct drm_encoder *encoder)
 {
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 489ea94693ff..f917a979e4a4 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -729,10 +729,11 @@ static int sun8i_hdmi_phy_probe(struct platform_device 
*pdev)
return 0;
 }
 
-struct platform_driver sun8i_hdmi_phy_driver = {
+static struct platform_driver sun8i_hdmi_phy_driver = {
.probe  = sun8i_hdmi_phy_probe,
.driver = {
.name = "sun8i-hdmi-phy",
.of_match_table = sun8i_hdmi_phy_of_table,
},
 };
+module_platform_driver(sun8i_hdmi_phy_driver);
-- 
2.42.0



[PATCH 6/7] drm/sun4i: dw-hdmi: Make sun8i_hdmi_phy_get() more intuitive

2023-09-24 Thread Jernej Skrabec
Let's make sun8i_hdmi_phy_get() to behave more like other kernel
functions and return phy pointer instead of setting field in struct.
This also makes function more universal.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c  |  5 +++--
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |  2 +-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 10 --
 3 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index d93e8ff71aae..41f815a1faec 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -239,10 +239,11 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
goto err_disable_clk_tmds;
}
 
-   ret = sun8i_hdmi_phy_get(hdmi, phy_node);
+   hdmi->phy = sun8i_hdmi_phy_get(phy_node);
of_node_put(phy_node);
-   if (ret) {
+   if (IS_ERR(hdmi->phy)) {
dev_err(dev, "Couldn't get the HDMI PHY\n");
+   ret = PTR_ERR(hdmi->phy);
goto err_disable_clk_tmds;
}
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 21e010deeb48..748b6a4d9cdd 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -200,7 +200,7 @@ encoder_to_sun8i_dw_hdmi(struct drm_encoder *encoder)
return container_of(encoder, struct sun8i_dw_hdmi, encoder);
 }
 
-int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node);
+struct sun8i_hdmi_phy *sun8i_hdmi_phy_get(struct device_node *node);
 
 int sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
 void sun8i_hdmi_phy_deinit(struct sun8i_hdmi_phy *phy);
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index f917a979e4a4..1c9bdefed35e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -650,25 +650,23 @@ static const struct of_device_id 
sun8i_hdmi_phy_of_table[] = {
{ /* sentinel */ }
 };
 
-int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
+struct sun8i_hdmi_phy *sun8i_hdmi_phy_get(struct device_node *node)
 {
struct platform_device *pdev = of_find_device_by_node(node);
struct sun8i_hdmi_phy *phy;
 
if (!pdev)
-   return -EPROBE_DEFER;
+   return ERR_PTR(-EPROBE_DEFER);
 
phy = platform_get_drvdata(pdev);
if (!phy) {
put_device(>dev);
-   return -EPROBE_DEFER;
+   return ERR_PTR(-EPROBE_DEFER);
}
 
-   hdmi->phy = phy;
-
put_device(>dev);
 
-   return 0;
+   return phy;
 }
 
 static int sun8i_hdmi_phy_probe(struct platform_device *pdev)
-- 
2.42.0



[PATCH 7/7] drm/sun4i: dw-hdmi: check for phy device first

2023-09-24 Thread Jernej Skrabec
Let's check for phy device first. Since it uses much of the same clocks
and resets it also lowers amount of possible deferred probes.

While at it, don't report error for deferred phy probe.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 35 +--
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 41f815a1faec..c1becd964326 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -173,11 +173,24 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
struct device_node *phy_node;
struct drm_encoder *encoder;
struct sun8i_dw_hdmi *hdmi;
+   struct sun8i_hdmi_phy *phy;
int ret;
 
if (!pdev->dev.of_node)
return -ENODEV;
 
+   phy_node = of_parse_phandle(dev->of_node, "phys", 0);
+   if (!phy_node) {
+   dev_err(dev, "Can't find PHY phandle\n");
+   return -EINVAL;
+   }
+
+   phy = sun8i_hdmi_phy_get(phy_node);
+   of_node_put(phy_node);
+   if (IS_ERR(phy))
+   return dev_err_probe(dev, PTR_ERR(phy),
+"Couldn't get the HDMI PHY\n");
+
hdmi = drmm_kzalloc(drm, sizeof(*hdmi), GFP_KERNEL);
if (!hdmi)
return -ENOMEM;
@@ -185,6 +198,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
plat_data = >plat_data;
hdmi->dev = >dev;
encoder = >encoder;
+   hdmi->phy = phy;
 
hdmi->quirks = of_device_get_match_data(dev);
 
@@ -232,22 +246,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
goto err_assert_ctrl_reset;
}
 
-   phy_node = of_parse_phandle(dev->of_node, "phys", 0);
-   if (!phy_node) {
-   dev_err(dev, "Can't found PHY phandle\n");
-   ret = -EINVAL;
-   goto err_disable_clk_tmds;
-   }
-
-   hdmi->phy = sun8i_hdmi_phy_get(phy_node);
-   of_node_put(phy_node);
-   if (IS_ERR(hdmi->phy)) {
-   dev_err(dev, "Couldn't get the HDMI PHY\n");
-   ret = PTR_ERR(hdmi->phy);
-   goto err_disable_clk_tmds;
-   }
-
-   ret = sun8i_hdmi_phy_init(hdmi->phy);
+   ret = sun8i_hdmi_phy_init(phy);
if (ret)
goto err_disable_clk_tmds;
 
@@ -259,7 +258,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
plat_data->mode_valid = hdmi->quirks->mode_valid;
plat_data->use_drm_infoframe = hdmi->quirks->use_drm_infoframe;
plat_data->output_port = 1;
-   sun8i_hdmi_phy_set_ops(hdmi->phy, plat_data);
+   sun8i_hdmi_phy_set_ops(phy, plat_data);
 
platform_set_drvdata(pdev, hdmi);
 
@@ -310,7 +309,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
drm_bridge_remove(>enc_bridge);
dw_hdmi_remove(hdmi->hdmi);
 err_deinit_phy:
-   sun8i_hdmi_phy_deinit(hdmi->phy);
+   sun8i_hdmi_phy_deinit(phy);
 err_disable_clk_tmds:
clk_disable_unprepare(hdmi->clk_tmds);
 err_assert_ctrl_reset:
-- 
2.42.0



[PATCH 3/7] drm/sun4i: dw-hdmi: Switch to bridge functions

2023-09-24 Thread Jernej Skrabec
Since ddc-en property handling was moved from sun8i dw-hdmi driver to
display connector driver, probe order of drivers determines if EDID is
properly read at boot time or not.

In order to fix this, let's switch to bridge functions which allows us
to build proper chain and defer execution until all drivers are probed.

Fixes: 920169041baa ("drm/sun4i: dw-hdmi: Fix ddc-en GPIO consumer conflict")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 114 +-
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h |   5 ++
 2 files changed, 117 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 8f8d3bdba5ce..93831cdf1917 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -8,14 +8,82 @@
 #include 
 #include 
 
+#include 
+#include 
 #include 
 #include 
 #include 
 #include 
 
+#include 
+
 #include "sun8i_dw_hdmi.h"
 #include "sun8i_tcon_top.h"
 
+#define bridge_to_sun8i_dw_hdmi(x) \
+   container_of(x, struct sun8i_dw_hdmi, enc_bridge)
+
+static int sun8i_hdmi_enc_attach(struct drm_bridge *bridge,
+enum drm_bridge_attach_flags flags)
+{
+   struct sun8i_dw_hdmi *hdmi = bridge_to_sun8i_dw_hdmi(bridge);
+
+   return drm_bridge_attach(>encoder, hdmi->hdmi_bridge,
+>enc_bridge, flags);
+}
+
+static void sun8i_hdmi_enc_detach(struct drm_bridge *bridge)
+{
+   struct sun8i_dw_hdmi *hdmi = bridge_to_sun8i_dw_hdmi(bridge);
+
+   cec_notifier_conn_unregister(hdmi->cec_notifier);
+   hdmi->cec_notifier = NULL;
+}
+
+static void sun8i_hdmi_enc_hpd_notify(struct drm_bridge *bridge,
+ enum drm_connector_status status)
+{
+   struct sun8i_dw_hdmi *hdmi = bridge_to_sun8i_dw_hdmi(bridge);
+   struct edid *edid;
+
+   if (!hdmi->cec_notifier)
+   return;
+
+   if (status == connector_status_connected) {
+   edid = drm_bridge_get_edid(hdmi->hdmi_bridge, hdmi->connector);
+   if (edid)
+   cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier,
+edid);
+   } else {
+   cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
+   }
+}
+
+static int sun8i_hdmi_enc_atomic_check(struct drm_bridge *bridge,
+  struct drm_bridge_state *bridge_state,
+  struct drm_crtc_state *crtc_state,
+  struct drm_connector_state *conn_state)
+{
+   struct drm_connector_state *old_conn_state =
+   drm_atomic_get_old_connector_state(conn_state->state,
+  conn_state->connector);
+
+   if (!drm_connector_atomic_hdr_metadata_equal(old_conn_state, 
conn_state))
+   crtc_state->mode_changed = true;
+
+   return 0;
+}
+
+static const struct drm_bridge_funcs sun8i_hdmi_enc_bridge_funcs = {
+   .attach = sun8i_hdmi_enc_attach,
+   .detach = sun8i_hdmi_enc_detach,
+   .hpd_notify = sun8i_hdmi_enc_hpd_notify,
+   .atomic_check = sun8i_hdmi_enc_atomic_check,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+   .atomic_reset = drm_atomic_helper_bridge_reset,
+};
+
 static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder *encoder,
   struct drm_display_mode *mode,
   struct drm_display_mode *adj_mode)
@@ -99,6 +167,8 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
 {
struct platform_device *pdev = to_platform_device(dev);
struct dw_hdmi_plat_data *plat_data;
+   struct cec_connector_info conn_info;
+   struct drm_connector *connector;
struct drm_device *drm = data;
struct device_node *phy_node;
struct drm_encoder *encoder;
@@ -187,18 +257,57 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
 
plat_data->mode_valid = hdmi->quirks->mode_valid;
plat_data->use_drm_infoframe = hdmi->quirks->use_drm_infoframe;
+   plat_data->output_port = 1;
sun8i_hdmi_phy_set_ops(hdmi->phy, plat_data);
 
platform_set_drvdata(pdev, hdmi);
 
-   hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
+   hdmi->hdmi = dw_hdmi_probe(pdev, plat_data);
if (IS_ERR(hdmi->hdmi)) {
ret = PTR_ERR(hdmi->hdmi);
goto err_deinit_phy;
}
 
+   hdmi->hdmi_bridge = of_drm_find_bridge(dev->of_node);
+
+   hdmi->enc_bridge.funcs = _hdmi_enc_bridge_funcs;
+   hdmi->en

[PATCH 2/7] drm/sun4i: dw-hdmi: Remove double encoder cleanup

2023-09-24 Thread Jernej Skrabec
It turns out that comment is wrong - dw hdmi driver never does any
encoder cleanup. In fact, cleanup is done automatically, in destroy
callback of encoder. Even more, encoder memory will be freed when hdmi
device is destroyed. However, encoder will be cleaned up after that, in
drm_mode_config_cleanup(), which is called later. This will cause use
after free bug.

Remove redundant encoder cleanup, switch memory allocation to live as
long as drm object and while at it, check return code of encoder
initialization.

Fixes: b7c7436a5ff0 ("drm/sun4i: Implement A83T HDMI driver")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 17 +++--
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 0b647b030b15..8f8d3bdba5ce 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -107,7 +108,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
if (!pdev->dev.of_node)
return -ENODEV;
 
-   hdmi = devm_kzalloc(>dev, sizeof(*hdmi), GFP_KERNEL);
+   hdmi = drmm_kzalloc(drm, sizeof(*hdmi), GFP_KERNEL);
if (!hdmi)
return -ENOMEM;
 
@@ -180,7 +181,9 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
goto err_disable_clk_tmds;
 
drm_encoder_helper_add(encoder, _dw_hdmi_encoder_helper_funcs);
-   drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
+   ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
+   if (ret)
+   goto err_deinit_phy;
 
plat_data->mode_valid = hdmi->quirks->mode_valid;
plat_data->use_drm_infoframe = hdmi->quirks->use_drm_infoframe;
@@ -189,20 +192,14 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
platform_set_drvdata(pdev, hdmi);
 
hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
-
-   /*
-* If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
-* which would have called the encoder cleanup.  Do it manually.
-*/
if (IS_ERR(hdmi->hdmi)) {
ret = PTR_ERR(hdmi->hdmi);
-   goto cleanup_encoder;
+   goto err_deinit_phy;
}
 
return 0;
 
-cleanup_encoder:
-   drm_encoder_cleanup(encoder);
+err_deinit_phy:
sun8i_hdmi_phy_deinit(hdmi->phy);
 err_disable_clk_tmds:
clk_disable_unprepare(hdmi->clk_tmds);
-- 
2.42.0



[PATCH 0/7] drm/sun4i: dw-hdmi: Fix initialization & refactor

2023-09-24 Thread Jernej Skrabec
Main goal of this series is to fix race condition between probing display
connector driver and sun8i dw-hdmi platform driver. Sometimes, boards have
ddc-en gpio specified in DT file. This is handled by display connector
driver since commit 920169041baa ("drm/sun4i: dw-hdmi: Fix ddc-en GPIO
consumer conflict"). However, because there is no link between it and
sun8i dw-hdmi driver, probe order isn't determined. If display connector
driver if probed afterwards, then sun8i dw-hdmi driver won't be able to
read EDID and thus fall back to 1024x768. This can be easily solved by
using bridges and linking them together. Coincidentally, switching to
bridge model is also long term goal.

I found out some other issues when working on them (missing phy deinit and
memory corruption during executing fail path). Since there is now a bigger
chance of deferring probe, it's also good to skip reporting deferred probe
as error. This often confuses users when examining dmesg output, especially
if there is no error code reported.

I also throw 2 refactoring patches for a good measure.

Please take a look.

Best regards,
Jernej

Jernej Skrabec (7):
  drm/sun4i: dw-hdmi: Deinit PHY in fail path
  drm/sun4i: dw-hdmi: Remove double encoder cleanup
  drm/sun4i: dw-hdmi: Switch to bridge functions
  drm/sun4i: Don't show error for deferred probes.
  drm/sun4i: dw-hdmi: Split driver registration
  drm/sun4i: dw-hdmi: Make sun8i_hdmi_phy_get() more intuitive
  drm/sun4i: dw-hdmi: check for phy device first

 drivers/gpu/drm/sun4i/sun4i_drv.c  |   3 +-
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c  | 191 ++---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |   9 +-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c |  13 +-
 4 files changed, 151 insertions(+), 65 deletions(-)

-- 
2.42.0



[PATCH] drm/bridge: dw-hdmi-cec: Add arbitration lost event

2023-09-09 Thread Jernej Skrabec
Add handling of arbitration lost event.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
index be21c11de1f2..673661160e54 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
@@ -145,6 +145,10 @@ static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data)
cec->tx_status = CEC_TX_STATUS_NACK;
cec->tx_done = true;
ret = IRQ_WAKE_THREAD;
+   } else if (stat & CEC_STAT_ARBLOST) {
+   cec->tx_status = CEC_TX_STATUS_ARB_LOST;
+   cec->tx_done = true;
+   ret = IRQ_WAKE_THREAD;
}
 
if (stat & CEC_STAT_EOM) {
@@ -209,7 +213,7 @@ static int dw_hdmi_cec_enable(struct cec_adapter *adap, 
bool enable)
cec->ops->enable(cec->hdmi);
 
irqs = CEC_STAT_ERROR_INIT | CEC_STAT_NACK | CEC_STAT_EOM |
-  CEC_STAT_DONE;
+  CEC_STAT_ARBLOST | CEC_STAT_DONE;
dw_hdmi_write(cec, irqs, HDMI_CEC_POLARITY);
dw_hdmi_write(cec, ~irqs, HDMI_CEC_MASK);
dw_hdmi_write(cec, ~irqs, HDMI_IH_MUTE_CEC_STAT0);
-- 
2.42.0



[PATCH 1/3] dt-bindings: display: synopsys, dw-hdmi: Add property for disabling CEC

2023-04-15 Thread Jernej Skrabec
Even though some DW-HDMI controllers have perfectly usable HDMI-CEC
implementation, some boards might prefer not to use it or even use
software implementation instead.

Add property for disabling CEC so driver doesn't expose unused CEC
interface, if CEC pin isn't connected anywhere.

Signed-off-by: Jernej Skrabec 
---
 .../devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml | 5 +
 1 file changed, 5 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml 
b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml
index 4b7e54a8f037..624d32c024f6 100644
--- a/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml
@@ -48,6 +48,11 @@ properties:
   interrupts:
 maxItems: 1
 
+  snps,disable-cec:
+$ref: /schemas/types.yaml#/definitions/flag
+description:
+  Disable HDMI-CEC.
+
 additionalProperties: true
 
 ...
-- 
2.40.0



[PATCH 3/3] ARM: dts: sun8i: h3: beelink-x2: Disable DW-HDMI CEC

2023-04-15 Thread Jernej Skrabec
Beelink X2 uses software implementation of CEC even though DW-HDMI has
working hardware implementation.

Disable unused DW-HDMI CEC.

Signed-off-by: Jernej Skrabec 
---
 arch/arm/boot/dts/sun8i-h3-beelink-x2.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts 
b/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
index a6d38ecee141..38f40d69e5c5 100644
--- a/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
+++ b/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
@@ -150,6 +150,7 @@  {
 };
 
  {
+   snps,disable-cec;
status = "okay";
 };
 
-- 
2.40.0



[PATCH 2/3] drm/bridge: dw_hdmi: Handle snps,disable-cec property

2023-04-15 Thread Jernej Skrabec
New DT property allows to skip CEC initialization.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 603bb3c51027..e7e8199d2fb1 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -3615,7 +3615,9 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device 
*pdev,
hdmi->audio = platform_device_register_full();
}
 
-   if (!plat_data->disable_cec && (config0 & HDMI_CONFIG0_CEC)) {
+   if (!plat_data->disable_cec &&
+   !of_property_read_bool(np, "snps,disable-cec") &&
+   (config0 & HDMI_CONFIG0_CEC)) {
cec.hdmi = hdmi;
cec.ops = _hdmi_cec_ops;
cec.irq = irq;
-- 
2.40.0



[PATCH 0/3] drm/bridge: dw_hdmi: allow to disable CEC from DT

2023-04-15 Thread Jernej Skrabec
Boards can have perfectly working DW HDMI CEC implementation but they
may prefer to use bit banged implementation instead. This is the
situation on Beelink X2.

Add DW HDMI DT property for disabling CEC. This prevents confusion on
userspace side by not exposing unused CEC interface.

Best regards,
Jernej

Jernej Skrabec (3):
  dt-bindings: display: synopsys,dw-hdmi: Add property for disabling CEC
  drm/bridge: dw_hdmi: Handle snps,disable-cec property
  ARM: dts: sun8i: h3: beelink-x2: Disable DW-HDMI CEC

 .../devicetree/bindings/display/bridge/synopsys,dw-hdmi.yaml | 5 +
 arch/arm/boot/dts/sun8i-h3-beelink-x2.dts| 1 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c| 4 +++-
 3 files changed, 9 insertions(+), 1 deletion(-)

-- 
2.40.0



[PATCH v2] drm/sun4i: Add DMA mask and segment size

2022-06-20 Thread Jernej Skrabec
Kernel occasionally complains that there is mismatch in segment size
when trying to render HW decoded videos and rendering them directly with
sun4i DRM driver. Following message can be observed on H6 SoC:

[  184.298308] [ cut here ]
[  184.298326] DMA-API: sun4i-drm display-engine: mapping sg segment longer 
than device claims to support [len=6144000] [max=65536]
[  184.298364] WARNING: CPU: 1 PID: 382 at kernel/dma/debug.c:1162 
debug_dma_map_sg+0x2b0/0x350
[  184.322997] CPU: 1 PID: 382 Comm: ffmpeg Not tainted 5.19.0-rc1+ #1331
[  184.329533] Hardware name: Tanix TX6 (DT)
[  184.333544] pstate: 6005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[  184.340512] pc : debug_dma_map_sg+0x2b0/0x350
[  184.344882] lr : debug_dma_map_sg+0x2b0/0x350
[  184.349250] sp : 89f33a50
[  184.352567] x29: 89f33a50 x28: 0001 x27: 01b86c00
[  184.359725] x26:  x25: 05d8cc80 x24: 
[  184.366879] x23: 8939ab18 x22: 0001 x21: 0001
[  184.374031] x20:  x19: 018a7410 x18: 
[  184.381186] x17:  x16:  x15: 
[  184.388338] x14: 0001 x13: 89534e86 x12: 6f70707573206f74
[  184.395493] x11: 20736d69616c6320 x10: 000a x9 : 0001
[  184.402647] x8 : 893b6d40 x7 : 89f33850 x6 : 000c
[  184.409800] x5 : bf997940 x4 :  x3 : 0027
[  184.416953] x2 :  x1 :  x0 : 03960e80
[  184.424106] Call trace:
[  184.426556]  debug_dma_map_sg+0x2b0/0x350
[  184.430580]  __dma_map_sg_attrs+0xa0/0x110
[  184.434687]  dma_map_sgtable+0x28/0x4c
[  184.438447]  vb2_dc_dmabuf_ops_map+0x60/0xcc
[  184.442729]  __map_dma_buf+0x2c/0xd4
[  184.446321]  dma_buf_map_attachment+0xa0/0x130
[  184.450777]  drm_gem_prime_import_dev+0x7c/0x18c
[  184.455410]  drm_gem_prime_fd_to_handle+0x1b8/0x214
[  184.460300]  drm_prime_fd_to_handle_ioctl+0x2c/0x40
[  184.465190]  drm_ioctl_kernel+0xc4/0x174
[  184.469123]  drm_ioctl+0x204/0x420
[  184.472534]  __arm64_sys_ioctl+0xac/0xf0
[  184.476474]  invoke_syscall+0x48/0x114
[  184.480240]  el0_svc_common.constprop.0+0x44/0xec
[  184.484956]  do_el0_svc+0x2c/0xc0
[  184.488283]  el0_svc+0x2c/0x84
[  184.491354]  el0t_64_sync_handler+0x11c/0x150
[  184.495723]  el0t_64_sync+0x18c/0x190
[  184.499397] ---[ end trace  ]---

Fix that by setting DMA mask and segment size.

Signed-off-by: Jernej Skrabec 
---
Changes from v1:
- added comment
- updated commit message with kernel report

 drivers/gpu/drm/sun4i/sun4i_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c 
b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 275f7e4a03ae..f135a6b3cadb 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -7,6 +7,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -367,6 +368,13 @@ static int sun4i_drv_probe(struct platform_device *pdev)
 
INIT_KFIFO(list.fifo);
 
+   /*
+* DE2 and DE3 cores actually supports 40-bit addresses, but
+* driver does not.
+*/
+   dma_set_mask_and_coherent(>dev, DMA_BIT_MASK(32));
+   dma_set_max_seg_size(>dev, DMA_BIT_MASK(32));
+
for (i = 0;; i++) {
struct device_node *pipeline = of_parse_phandle(np,

"allwinner,pipelines",
-- 
2.36.1



[PATCH] drm/sun4i: Add DMA mask and segment size

2022-06-16 Thread Jernej Skrabec
Kernel occasionally complains that there is mismatch in segment size
when trying to render HW decoded videos and rendering them directly with
sun4i DRM driver.

Fix that by setting DMA mask and segment size.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun4i_drv.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c 
b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 275f7e4a03ae..83f4e87f77f6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -7,6 +7,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -367,6 +368,9 @@ static int sun4i_drv_probe(struct platform_device *pdev)
 
INIT_KFIFO(list.fifo);
 
+   dma_set_mask_and_coherent(>dev, DMA_BIT_MASK(32));
+   dma_set_max_seg_size(>dev, DMA_BIT_MASK(32));
+
for (i = 0;; i++) {
struct device_node *pipeline = of_parse_phandle(np,

"allwinner,pipelines",
-- 
2.36.1



[PATCH] drm/sun4i: mixer: Fix P010 and P210 format numbers

2022-02-28 Thread Jernej Skrabec
It turns out that DE3 manual has inverted YUV and YVU format numbers for
P010 and P210. Invert them.

This was tested by playing video decoded to P010 and additionally
confirmed by looking at BSP driver source.

Fixes: 169ca4b38932 ("drm/sun4i: Add separate DE3 VI layer formats")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h 
b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 145833a9d82d..5b3fbee18671 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -111,10 +111,10 @@
 /* format 13 is semi-planar YUV411 VUVU */
 #define SUN8I_MIXER_FBFMT_YUV411   14
 /* format 15 doesn't exist */
-/* format 16 is P010 YVU */
-#define SUN8I_MIXER_FBFMT_P010_YUV 17
-/* format 18 is P210 YVU */
-#define SUN8I_MIXER_FBFMT_P210_YUV 19
+#define SUN8I_MIXER_FBFMT_P010_YUV 16
+/* format 17 is P010 YVU */
+#define SUN8I_MIXER_FBFMT_P210_YUV 18
+/* format 19 is P210 YVU */
 /* format 20 is packed YVU444 10-bit */
 /* format 21 is packed YUV444 10-bit */
 
-- 
2.35.1



[PATCH] drm/sun4i: virtual CMA addresses are not needed

2021-10-19 Thread Jernej Skrabec
Driver never uses virtual address of DRM CMA buffers. Switch to CMA
helpers which don't deal with virtual mapping.

This was actually already the case before commit ad408c766cef
("drm/sun4i: Use DRM_GEM_CMA_VMAP_DRIVER_OPS for GEM operations"),
but only convenient macro at the time used helpers with virtual
mapping.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun4i_drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c 
b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 54dd562e294c..b630614b3d72 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -53,7 +53,7 @@ static const struct drm_driver sun4i_drv_driver = {
.minor  = 0,
 
/* GEM Operations */
-   DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(drm_sun4i_gem_dumb_create),
+   DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_sun4i_gem_dumb_create),
 };
 
 static int sun4i_drv_bind(struct device *dev)
-- 
2.33.1



[PATCH v2] drm/sun4i: dw-hdmi: Fix HDMI PHY clock setup

2021-09-15 Thread Jernej Skrabec
Recent rework, which made HDMI PHY driver a platform device, inadvertely
reversed clock setup order. HW is very touchy about it. Proper way is to
handle controllers resets and clocks first and HDMI PHYs second.

Currently, without this fix, first mode set completely fails (nothing on
HDMI monitor) on H3 era PHYs. On H6, it still somehow work.

Move HDMI PHY reset & clocks handling to sun8i_hdmi_phy_init() which
will assure that code is executed after controllers reset & clocks are
handled. Additionally, add sun8i_hdmi_phy_deinit() which will deinit
them at controllers driver unload.

Tested on A64, H3, H6 and R40.

Fixes: 9bf3797796f5 ("drm/sun4i: dw-hdmi: Make HDMI PHY into a platform device")
Signed-off-by: Jernej Skrabec 
---

Changes from v1:
- if sun8i_hdmi_phy_init() fails, go to error hanling instead of returning
  immediately
- rename err_deassert_rst_phy -> err_assert_rst_phy

 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c  |  7 +-
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |  4 +-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 97 ++
 3 files changed, 61 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index f75fb157f2ff..016b877051da 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -216,11 +216,13 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
goto err_disable_clk_tmds;
}
 
+   ret = sun8i_hdmi_phy_init(hdmi->phy);
+   if (ret)
+   goto err_disable_clk_tmds;
+
drm_encoder_helper_add(encoder, _dw_hdmi_encoder_helper_funcs);
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
-   sun8i_hdmi_phy_init(hdmi->phy);
-
plat_data->mode_valid = hdmi->quirks->mode_valid;
plat_data->use_drm_infoframe = hdmi->quirks->use_drm_infoframe;
sun8i_hdmi_phy_set_ops(hdmi->phy, plat_data);
@@ -262,6 +264,7 @@ static void sun8i_dw_hdmi_unbind(struct device *dev, struct 
device *master,
struct sun8i_dw_hdmi *hdmi = dev_get_drvdata(dev);
 
dw_hdmi_unbind(hdmi->hdmi);
+   sun8i_hdmi_phy_deinit(hdmi->phy);
clk_disable_unprepare(hdmi->clk_tmds);
reset_control_assert(hdmi->rst_ctrl);
gpiod_set_value(hdmi->ddc_en, 0);
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 74f6ed0e2570..bffe1b9cd3dc 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -169,6 +169,7 @@ struct sun8i_hdmi_phy {
struct clk  *clk_phy;
struct clk  *clk_pll0;
struct clk  *clk_pll1;
+   struct device   *dev;
unsigned intrcal;
struct regmap   *regs;
struct reset_control*rst_phy;
@@ -205,7 +206,8 @@ encoder_to_sun8i_dw_hdmi(struct drm_encoder *encoder)
 
 int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node);
 
-void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
+int sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
+void sun8i_hdmi_phy_deinit(struct sun8i_hdmi_phy *phy);
 void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
struct dw_hdmi_plat_data *plat_data);
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index c9239708d398..b64d93da651d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -506,9 +506,60 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy 
*phy)
phy->rcal = (val & SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK) >> 2;
 }
 
-void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
+int sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
 {
+   int ret;
+
+   ret = reset_control_deassert(phy->rst_phy);
+   if (ret) {
+   dev_err(phy->dev, "Cannot deassert phy reset control: %d\n", 
ret);
+   return ret;
+   }
+
+   ret = clk_prepare_enable(phy->clk_bus);
+   if (ret) {
+   dev_err(phy->dev, "Cannot enable bus clock: %d\n", ret);
+   goto err_assert_rst_phy;
+   }
+
+   ret = clk_prepare_enable(phy->clk_mod);
+   if (ret) {
+   dev_err(phy->dev, "Cannot enable mod clock: %d\n", ret);
+   goto err_disable_clk_bus;
+   }
+
+   if (phy->variant->has_phy_clk) {
+   ret = sun8i_phy_clk_create(phy, phy->dev,
+  phy->variant->has_second_pll);
+   if (ret) {
+   dev_err(phy->dev, "Couldn't create the PHY clock\n");
+   goto err_disable_clk_mod;
+

[PATCH] drm/sun4i: dw-hdmi: Fix HDMI PHY clock setup

2021-09-13 Thread Jernej Skrabec
Recent rework, which made HDMI PHY driver a platform device, inadvertely
reversed clock setup order. HW is very touchy about it. Proper way is to
handle controllers resets and clocks first and HDMI PHYs second.

Currently, without this fix, first mode set completely fails (nothing on
HDMI monitor) on H3 era PHYs. On H6, it still somehow work.

Move HDMI PHY reset & clocks handling to sun8i_hdmi_phy_init() which
will assure that code is executed after controllers reset & clocks are
handled. Additionally, add sun8i_hdmi_phy_deinit() which will deinit
them at controllers driver unload.

Tested on A64, H3, H6 and R40.

Fixes: 9bf3797796f5 ("drm/sun4i: dw-hdmi: Make HDMI PHY into a platform device")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c  |  7 +-
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |  4 +-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 97 ++
 3 files changed, 61 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index f75fb157f2ff..5fa5407ac583 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -216,11 +216,13 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
goto err_disable_clk_tmds;
}
 
+   ret = sun8i_hdmi_phy_init(hdmi->phy);
+   if (ret)
+   return ret;
+
drm_encoder_helper_add(encoder, _dw_hdmi_encoder_helper_funcs);
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
-   sun8i_hdmi_phy_init(hdmi->phy);
-
plat_data->mode_valid = hdmi->quirks->mode_valid;
plat_data->use_drm_infoframe = hdmi->quirks->use_drm_infoframe;
sun8i_hdmi_phy_set_ops(hdmi->phy, plat_data);
@@ -262,6 +264,7 @@ static void sun8i_dw_hdmi_unbind(struct device *dev, struct 
device *master,
struct sun8i_dw_hdmi *hdmi = dev_get_drvdata(dev);
 
dw_hdmi_unbind(hdmi->hdmi);
+   sun8i_hdmi_phy_deinit(hdmi->phy);
clk_disable_unprepare(hdmi->clk_tmds);
reset_control_assert(hdmi->rst_ctrl);
gpiod_set_value(hdmi->ddc_en, 0);
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 74f6ed0e2570..bffe1b9cd3dc 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -169,6 +169,7 @@ struct sun8i_hdmi_phy {
struct clk  *clk_phy;
struct clk  *clk_pll0;
struct clk  *clk_pll1;
+   struct device   *dev;
unsigned intrcal;
struct regmap   *regs;
struct reset_control*rst_phy;
@@ -205,7 +206,8 @@ encoder_to_sun8i_dw_hdmi(struct drm_encoder *encoder)
 
 int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node);
 
-void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
+int sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
+void sun8i_hdmi_phy_deinit(struct sun8i_hdmi_phy *phy);
 void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
struct dw_hdmi_plat_data *plat_data);
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index c9239708d398..78b152973957 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -506,9 +506,60 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy 
*phy)
phy->rcal = (val & SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK) >> 2;
 }
 
-void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
+int sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
 {
+   int ret;
+
+   ret = reset_control_deassert(phy->rst_phy);
+   if (ret) {
+   dev_err(phy->dev, "Cannot deassert phy reset control: %d\n", 
ret);
+   return ret;
+   }
+
+   ret = clk_prepare_enable(phy->clk_bus);
+   if (ret) {
+   dev_err(phy->dev, "Cannot enable bus clock: %d\n", ret);
+   goto err_deassert_rst_phy;
+   }
+
+   ret = clk_prepare_enable(phy->clk_mod);
+   if (ret) {
+   dev_err(phy->dev, "Cannot enable mod clock: %d\n", ret);
+   goto err_disable_clk_bus;
+   }
+
+   if (phy->variant->has_phy_clk) {
+   ret = sun8i_phy_clk_create(phy, phy->dev,
+  phy->variant->has_second_pll);
+   if (ret) {
+   dev_err(phy->dev, "Couldn't create the PHY clock\n");
+   goto err_disable_clk_mod;
+   }
+
+   clk_prepare_enable(phy->clk_phy);
+   }
+
phy->variant->phy_init(phy);
+
+   return 0;
+
+err_disable_clk_mod:
+   clk_disable_unprepare(phy->

[PATCH] drm/sun4i: Fix macros in sun8i_csc.h

2021-08-31 Thread Jernej Skrabec
Macros SUN8I_CSC_CTRL() and SUN8I_CSC_COEFF() don't follow usual
recommendation of having arguments enclosed in parenthesis. While that
didn't change anything for quiet sometime, it actually become important
after CSC code rework with commit ea067aee45a8 ("drm/sun4i: de2/de3:
Remove redundant CSC matrices").

Without this fix, colours are completely off for supported YVU formats
on SoCs with DE2 (A64, H3, R40, etc.).

Fix the issue by enclosing macro arguments in parenthesis.

Cc: sta...@vger.kernel.org # 5.12+
Fixes: 883029390550 ("drm/sun4i: Add DE2 CSC library")
Reported-by: Roman Stratiienko 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_csc.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h 
b/drivers/gpu/drm/sun4i/sun8i_csc.h
index a55a38ad849c..022cafa6c06c 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.h
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.h
@@ -16,8 +16,8 @@ struct sun8i_mixer;
 #define CCSC10_OFFSET 0xA
 #define CCSC11_OFFSET 0xF
 
-#define SUN8I_CSC_CTRL(base)   (base + 0x0)
-#define SUN8I_CSC_COEFF(base, i)   (base + 0x10 + 4 * i)
+#define SUN8I_CSC_CTRL(base)   ((base) + 0x0)
+#define SUN8I_CSC_COEFF(base, i)   ((base) + 0x10 + 4 * (i))
 
 #define SUN8I_CSC_CTRL_EN  BIT(0)
 
-- 
2.33.0



[PATCH] drm/sun4i: de3: Be explicit about supported modifiers

2021-06-05 Thread Jernej Skrabec
From: Piotr Oniszczuk 

Currently only linear formats are supported in sun4i-drm driver, but
SoCs like H6 supports AFBC variant of some of them in multiple cores
(GPU, VPU, DE3). Panfrost already implements AFBC compression and is
sometimes confused what should be default choice (linear, AFBC) if DRM
driver is not explicit about modifier support (MiniMyth2 distro with
MythTV app).

After some discussion with Daniel Stone on #panfrost IRC, it was decided
to make modifiers in sun4i-drm explicit, to avoid any kind of guessing,
not just in panfrost, but everywhere. In fact, long term idea is to make
modifier parameter in drm_universal_plane_init() mandatory (non NULL).

Signed-off-by: Piotr Oniszczuk 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 7 ++-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 8 +++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 0db164a774a1..e779855bcd6e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -370,6 +370,11 @@ static const u32 sun8i_ui_layer_formats[] = {
DRM_FORMAT_XRGB,
 };
 
+static const uint64_t sun8i_layer_modifiers[] = {
+   DRM_FORMAT_MOD_LINEAR,
+   DRM_FORMAT_MOD_INVALID
+};
+
 struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
   struct sun8i_mixer *mixer,
   int index)
@@ -392,7 +397,7 @@ struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct 
drm_device *drm,
   _ui_layer_funcs,
   sun8i_ui_layer_formats,
   ARRAY_SIZE(sun8i_ui_layer_formats),
-  NULL, type, NULL);
+  sun8i_layer_modifiers, type, NULL);
if (ret) {
dev_err(drm->dev, "Couldn't initialize layer\n");
return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 46420780db59..1c86c2dd0bbf 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -534,6 +534,11 @@ static const u32 sun8i_vi_layer_de3_formats[] = {
DRM_FORMAT_YVU422,
 };
 
+static const uint64_t sun8i_layer_modifiers[] = {
+   DRM_FORMAT_MOD_LINEAR,
+   DRM_FORMAT_MOD_INVALID
+};
+
 struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
   struct sun8i_mixer *mixer,
   int index)
@@ -560,7 +565,8 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct 
drm_device *drm,
ret = drm_universal_plane_init(drm, >plane, 0,
   _vi_layer_funcs,
   formats, format_count,
-  NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
+  sun8i_layer_modifiers,
+  DRM_PLANE_TYPE_OVERLAY, NULL);
if (ret) {
dev_err(drm->dev, "Couldn't initialize layer\n");
return ERR_PTR(ret);
-- 
2.31.1



[PATCH v3 5/5] drm/sun4i: dw-hdmi: Fix max. frequency for H6

2021-02-09 Thread Jernej Skrabec
It turns out that reasoning for lowering max. supported frequency is
wrong. Scrambling works just fine. Several now fixed bugs prevented
proper functioning, even with rates lower than 340 MHz. Issues were just
more pronounced with higher frequencies.

Fix that by allowing max. supported frequency in HW and fix the comment.

Fixes: cd9063757a22 ("drm/sun4i: DW HDMI: Lower max. supported rate for H6")
Reviewed-by: Chen-Yu Tsai 
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 23773a5e0650..bbdfd5e26ec8 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -47,11 +47,9 @@ sun8i_dw_hdmi_mode_valid_h6(struct dw_hdmi *hdmi, void *data,
 {
/*
 * Controller support maximum of 594 MHz, which correlates to
-* 4K@60Hz 4:4:4 or RGB. However, for frequencies greater than
-* 340 MHz scrambling has to be enabled. Because scrambling is
-* not yet implemented, just limit to 340 MHz for now.
+* 4K@60Hz 4:4:4 or RGB.
 */
-   if (mode->clock > 34)
+   if (mode->clock > 594000)
return MODE_CLOCK_HIGH;
 
return MODE_OK;
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 4/5] drm/sun4i: Fix H6 HDMI PHY configuration

2021-02-09 Thread Jernej Skrabec
As it turns out, vendor HDMI PHY driver for H6 has a pretty big table
of predefined values for various pixel clocks. However, most of them are
not useful/tested because they come from reference driver code. Vendor
PHY driver is concerned with only few of those, namely 27 MHz, 74.25
MHz, 148.5 MHz, 297 MHz and 594 MHz. These are all frequencies for
standard CEA modes.

Fix sun50i_h6_cur_ctr and sun50i_h6_phy_config with the values only for
aforementioned frequencies.

Table sun50i_h6_mpll_cfg doesn't need to be changed because values are
actually frequency dependant and not so much SoC dependant. See i.MX6
documentation for explanation of those values for similar PHY.

Fixes: c71c9b2fee17 ("drm/sun4i: Add support for Synopsys HDMI PHY")
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 26 +-
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 35c2133724e2..9994edf67509 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -104,29 +104,21 @@ static const struct dw_hdmi_mpll_config 
sun50i_h6_mpll_cfg[] = {
 
 static const struct dw_hdmi_curr_ctrl sun50i_h6_cur_ctr[] = {
/* pixelclkbpp8bpp10   bpp12 */
-   { 25175000,  { 0x, 0x, 0x }, },
{ 2700,  { 0x0012, 0x, 0x }, },
-   { 5940,  { 0x0008, 0x0008, 0x0008 }, },
-   { 7200,  { 0x0008, 0x0008, 0x001b }, },
-   { 7425,  { 0x0013, 0x0013, 0x0013 }, },
-   { 9000,  { 0x0008, 0x001a, 0x001b }, },
-   { 11880, { 0x001b, 0x001a, 0x001b }, },
-   { 14400, { 0x001b, 0x001a, 0x0034 }, },
-   { 18000, { 0x001b, 0x0033, 0x0034 }, },
-   { 21600, { 0x0036, 0x0033, 0x0034 }, },
-   { 23760, { 0x0036, 0x0033, 0x001b }, },
-   { 28800, { 0x0036, 0x001b, 0x001b }, },
-   { 29700, { 0x0019, 0x001b, 0x0019 }, },
-   { 33000, { 0x0036, 0x001b, 0x001b }, },
-   { 59400, { 0x003f, 0x001b, 0x001b }, },
+   { 7425,  { 0x0013, 0x001a, 0x001b }, },
+   { 14850, { 0x0019, 0x0033, 0x0034 }, },
+   { 29700, { 0x0019, 0x001b, 0x001b }, },
+   { 59400, { 0x0010, 0x001b, 0x001b }, },
{ ~0UL,  { 0x, 0x, 0x }, }
 };
 
 static const struct dw_hdmi_phy_config sun50i_h6_phy_config[] = {
/*pixelclk   symbol   term   vlev*/
-   { 7425,  0x8009, 0x0004, 0x0232},
-   { 14850, 0x8029, 0x0004, 0x0273},
-   { 59400, 0x8039, 0x0004, 0x014a},
+   { 2700,  0x8009, 0x0007, 0x02b0 },
+   { 7425,  0x8009, 0x0006, 0x022d },
+   { 14850, 0x8029, 0x0006, 0x0270 },
+   { 29700, 0x8039, 0x0005, 0x01ab },
+   { 59400, 0x8029, 0x, 0x008a },
{ ~0UL,  0x, 0x, 0x}
 };
 
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 3/5] drm/sun4i: dw-hdmi: always set clock rate

2021-02-09 Thread Jernej Skrabec
As expected, HDMI controller clock should always match pixel clock. In
the past, changing HDMI controller rate would seemingly worsen
situation. However, that was the result of other bugs which are now
fixed.

Fix that by removing set_rate quirk and always set clock rate.

Fixes: 40bb9d3147b2 ("drm/sun4i: Add support for H6 DW HDMI controller")
Reviewed-by: Chen-Yu Tsai 
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 4 +---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 1 -
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 92add2cef2e7..23773a5e0650 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -21,8 +21,7 @@ static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder 
*encoder,
 {
struct sun8i_dw_hdmi *hdmi = encoder_to_sun8i_dw_hdmi(encoder);
 
-   if (hdmi->quirks->set_rate)
-   clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000);
+   clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000);
 }
 
 static const struct drm_encoder_helper_funcs
@@ -295,7 +294,6 @@ static int sun8i_dw_hdmi_remove(struct platform_device 
*pdev)
 
 static const struct sun8i_dw_hdmi_quirks sun8i_a83t_quirks = {
.mode_valid = sun8i_dw_hdmi_mode_valid_a83t,
-   .set_rate = true,
 };
 
 static const struct sun8i_dw_hdmi_quirks sun50i_h6_quirks = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index d983746fa194..d4b55af0592f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -179,7 +179,6 @@ struct sun8i_dw_hdmi_quirks {
enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data,
   const struct drm_display_info *info,
   const struct drm_display_mode *mode);
-   unsigned int set_rate : 1;
unsigned int use_drm_infoframe : 1;
 };
 
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 2/5] drm/sun4i: tcon: set sync polarity for tcon1 channel

2021-02-09 Thread Jernej Skrabec
Channel 1 has polarity bits for vsync and hsync signals but driver never
sets them. It turns out that with pre-HDMI2 controllers seemingly there
is no issue if polarity is not set. However, with HDMI2 controllers
(H6) there often comes to de-synchronization due to phase shift. This
causes flickering screen. It's safe to assume that similar issues might
happen also with pre-HDMI2 controllers.

Solve issue with setting vsync and hsync polarity. Note that display
stacks with tcon top have polarity bits actually in tcon0 polarity
register.

Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
Reviewed-by: Chen-Yu Tsai 
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 25 +
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  6 ++
 2 files changed, 31 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 6b9af4c08cd6..9f06dec0fc61 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -672,6 +672,30 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
 SUN4I_TCON1_BASIC5_V_SYNC(vsync) |
 SUN4I_TCON1_BASIC5_H_SYNC(hsync));
 
+   /* Setup the polarity of multiple signals */
+   if (tcon->quirks->polarity_in_ch0) {
+   val = 0;
+
+   if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+   val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
+
+   if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+   val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
+
+   regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
+   } else {
+   /* according to vendor driver, this bit must be always set */
+   val = SUN4I_TCON1_IO_POL_UNKNOWN;
+
+   if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+   val |= SUN4I_TCON1_IO_POL_HSYNC_POSITIVE;
+
+   if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+   val |= SUN4I_TCON1_IO_POL_VSYNC_POSITIVE;
+
+   regmap_write(tcon->regs, SUN4I_TCON1_IO_POL_REG, val);
+   }
+
/* Map output pins to channel 1 */
regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
   SUN4I_TCON_GCTL_IOMAP_MASK,
@@ -1500,6 +1524,7 @@ static const struct sun4i_tcon_quirks 
sun8i_a83t_tv_quirks = {
 
 static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
.has_channel_1  = true,
+   .polarity_in_ch0= true,
.set_mux= sun8i_r40_tcon_tv_set_mux,
 };
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h 
b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index c5ac1b02482c..e624f6977eb8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -154,6 +154,11 @@
 #define SUN4I_TCON1_BASIC5_V_SYNC(height)  (((height) - 1) & 0x3ff)
 
 #define SUN4I_TCON1_IO_POL_REG 0xf0
+/* there is no documentation about this bit */
+#define SUN4I_TCON1_IO_POL_UNKNOWN BIT(26)
+#define SUN4I_TCON1_IO_POL_HSYNC_POSITIVE  BIT(25)
+#define SUN4I_TCON1_IO_POL_VSYNC_POSITIVE  BIT(24)
+
 #define SUN4I_TCON1_IO_TRI_REG 0xf4
 
 #define SUN4I_TCON_ECC_FIFO_REG0xf8
@@ -236,6 +241,7 @@ struct sun4i_tcon_quirks {
boolneeds_de_be_mux; /* sun6i needs mux to select backend */
boolneeds_edp_reset; /* a80 edp reset needed for tcon0 access */
boolsupports_lvds;   /* Does the TCON support an LVDS output? */
+   boolpolarity_in_ch0; /* some tcon1 channels have polarity bits in 
tcon0 pol register */
u8  dclk_min_div;   /* minimum divider for TCON0 DCLK */
 
/* callback to handle tcon muxing options */
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 1/5] clk: sunxi-ng: mp: fix parent rate change flag check

2021-02-09 Thread Jernej Skrabec
CLK_SET_RATE_PARENT flag is checked on parent clock instead of current
one. Fix that.

Fixes: 3f790433c3cb ("clk: sunxi-ng: Adjust MP clock parent rate when allowed")
Reviewed-by: Chen-Yu Tsai 
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/clk/sunxi-ng/ccu_mp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
index fa4ecb915590..9d3a76604d94 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -108,7 +108,7 @@ static unsigned long ccu_mp_round_rate(struct 
ccu_mux_internal *mux,
max_m = cmp->m.max ?: 1 << cmp->m.width;
max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
 
-   if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
+   if (!clk_hw_can_set_rate_parent(>common.hw)) {
ccu_mp_find_best(*parent_rate, rate, max_m, max_p, , );
rate = *parent_rate / p / m;
} else {
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 0/5] sunxi: fix H6 HDMI related issues

2021-02-09 Thread Jernej Skrabec
Over the year I got plenty of reports of troubles with H6 HDMI signal.
Sometimes monitor flickers, sometimes there was no image at all and
sometimes it didn't play well with AVR.

It turns out there are multiple issues. Patch 1 fixes clock issue,
which didn't adjust parent rate, even if it is allowed to do so. Patch 2
adds polarity config in tcon1. This is seemingly not needed for pre-HDMI2
controllers, although BSP drivers set it accordingly every time. It
turns out that HDMI2 controllers often don't work with monitors if
polarity is not set correctly. Patch 3 always set clock rate for HDMI
controller. Patch 4 fixes H6 HDMI PHY settings. Patch 5 fixes comment and
clock rate limit (wrong reasoning).

Please take a look.

Best regards,
Jernej

Changes from v2:
- use clk_hw_can_set_rate_parent() directly instead of checking flags
Changes from v1:
- collected Chen-Yu tags (except on replaced patch 4)
- Added some comments in patch 2
- Replaced patch 4 (see commit log for explanation)

Jernej Skrabec (5):
  clk: sunxi-ng: mp: fix parent rate change flag check
  drm/sun4i: tcon: set sync polarity for tcon1 channel
  drm/sun4i: dw-hdmi: always set clock rate
  drm/sun4i: Fix H6 HDMI PHY configuration
  drm/sun4i: dw-hdmi: Fix max. frequency for H6

 drivers/clk/sunxi-ng/ccu_mp.c  |  2 +-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 25 +
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  6 ++
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c  | 10 +++---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |  1 -
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 26 +-
 6 files changed, 44 insertions(+), 26 deletions(-)

--
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 5/5] drm/sun4i: dw-hdmi: Fix max. frequency for H6

2021-02-08 Thread Jernej Skrabec
It turns out that reasoning for lowering max. supported frequency is
wrong. Scrambling works just fine. Several now fixed bugs prevented
proper functioning, even with rates lower than 340 MHz. Issues were just
more pronounced with higher frequencies.

Fix that by allowing max. supported frequency in HW and fix the comment.

Fixes: cd9063757a22 ("drm/sun4i: DW HDMI: Lower max. supported rate for H6")
Reviewed-by: Chen-Yu Tsai 
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 23773a5e0650..bbdfd5e26ec8 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -47,11 +47,9 @@ sun8i_dw_hdmi_mode_valid_h6(struct dw_hdmi *hdmi, void *data,
 {
/*
 * Controller support maximum of 594 MHz, which correlates to
-* 4K@60Hz 4:4:4 or RGB. However, for frequencies greater than
-* 340 MHz scrambling has to be enabled. Because scrambling is
-* not yet implemented, just limit to 340 MHz for now.
+* 4K@60Hz 4:4:4 or RGB.
 */
-   if (mode->clock > 34)
+   if (mode->clock > 594000)
return MODE_CLOCK_HIGH;
 
return MODE_OK;
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 4/5] drm/sun4i: Fix H6 HDMI PHY configuration

2021-02-08 Thread Jernej Skrabec
As it turns out, vendor HDMI PHY driver for H6 has a pretty big table
of predefined values for various pixel clocks. However, most of them are
not useful/tested because they come from reference driver code. Vendor
PHY driver is concerned with only few of those, namely 27 MHz, 74.25
MHz, 148.5 MHz, 297 MHz and 594 MHz. These are all frequencies for
standard CEA modes.

Fix sun50i_h6_cur_ctr and sun50i_h6_phy_config with the values only for
aforementioned frequencies.

Table sun50i_h6_mpll_cfg doesn't need to be changed because values are
actually frequency dependant and not so much SoC dependant. See i.MX6
documentation for explanation of those values for similar PHY.

Fixes: c71c9b2fee17 ("drm/sun4i: Add support for Synopsys HDMI PHY")
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 26 +-
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 35c2133724e2..9994edf67509 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -104,29 +104,21 @@ static const struct dw_hdmi_mpll_config 
sun50i_h6_mpll_cfg[] = {
 
 static const struct dw_hdmi_curr_ctrl sun50i_h6_cur_ctr[] = {
/* pixelclkbpp8bpp10   bpp12 */
-   { 25175000,  { 0x, 0x, 0x }, },
{ 2700,  { 0x0012, 0x, 0x }, },
-   { 5940,  { 0x0008, 0x0008, 0x0008 }, },
-   { 7200,  { 0x0008, 0x0008, 0x001b }, },
-   { 7425,  { 0x0013, 0x0013, 0x0013 }, },
-   { 9000,  { 0x0008, 0x001a, 0x001b }, },
-   { 11880, { 0x001b, 0x001a, 0x001b }, },
-   { 14400, { 0x001b, 0x001a, 0x0034 }, },
-   { 18000, { 0x001b, 0x0033, 0x0034 }, },
-   { 21600, { 0x0036, 0x0033, 0x0034 }, },
-   { 23760, { 0x0036, 0x0033, 0x001b }, },
-   { 28800, { 0x0036, 0x001b, 0x001b }, },
-   { 29700, { 0x0019, 0x001b, 0x0019 }, },
-   { 33000, { 0x0036, 0x001b, 0x001b }, },
-   { 59400, { 0x003f, 0x001b, 0x001b }, },
+   { 7425,  { 0x0013, 0x001a, 0x001b }, },
+   { 14850, { 0x0019, 0x0033, 0x0034 }, },
+   { 29700, { 0x0019, 0x001b, 0x001b }, },
+   { 59400, { 0x0010, 0x001b, 0x001b }, },
{ ~0UL,  { 0x, 0x, 0x }, }
 };
 
 static const struct dw_hdmi_phy_config sun50i_h6_phy_config[] = {
/*pixelclk   symbol   term   vlev*/
-   { 7425,  0x8009, 0x0004, 0x0232},
-   { 14850, 0x8029, 0x0004, 0x0273},
-   { 59400, 0x8039, 0x0004, 0x014a},
+   { 2700,  0x8009, 0x0007, 0x02b0 },
+   { 7425,  0x8009, 0x0006, 0x022d },
+   { 14850, 0x8029, 0x0006, 0x0270 },
+   { 29700, 0x8039, 0x0005, 0x01ab },
+   { 59400, 0x8029, 0x, 0x008a },
{ ~0UL,  0x, 0x, 0x}
 };
 
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 3/5] drm/sun4i: dw-hdmi: always set clock rate

2021-02-08 Thread Jernej Skrabec
As expected, HDMI controller clock should always match pixel clock. In
the past, changing HDMI controller rate would seemingly worsen
situation. However, that was the result of other bugs which are now
fixed.

Fix that by removing set_rate quirk and always set clock rate.

Fixes: 40bb9d3147b2 ("drm/sun4i: Add support for H6 DW HDMI controller")
Reviewed-by: Chen-Yu Tsai 
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 4 +---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 1 -
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 92add2cef2e7..23773a5e0650 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -21,8 +21,7 @@ static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder 
*encoder,
 {
struct sun8i_dw_hdmi *hdmi = encoder_to_sun8i_dw_hdmi(encoder);
 
-   if (hdmi->quirks->set_rate)
-   clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000);
+   clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000);
 }
 
 static const struct drm_encoder_helper_funcs
@@ -295,7 +294,6 @@ static int sun8i_dw_hdmi_remove(struct platform_device 
*pdev)
 
 static const struct sun8i_dw_hdmi_quirks sun8i_a83t_quirks = {
.mode_valid = sun8i_dw_hdmi_mode_valid_a83t,
-   .set_rate = true,
 };
 
 static const struct sun8i_dw_hdmi_quirks sun50i_h6_quirks = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index d983746fa194..d4b55af0592f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -179,7 +179,6 @@ struct sun8i_dw_hdmi_quirks {
enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data,
   const struct drm_display_info *info,
   const struct drm_display_mode *mode);
-   unsigned int set_rate : 1;
unsigned int use_drm_infoframe : 1;
 };
 
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 2/5] drm/sun4i: tcon: set sync polarity for tcon1 channel

2021-02-08 Thread Jernej Skrabec
Channel 1 has polarity bits for vsync and hsync signals but driver never
sets them. It turns out that with pre-HDMI2 controllers seemingly there
is no issue if polarity is not set. However, with HDMI2 controllers
(H6) there often comes to de-synchronization due to phase shift. This
causes flickering screen. It's safe to assume that similar issues might
happen also with pre-HDMI2 controllers.

Solve issue with setting vsync and hsync polarity. Note that display
stacks with tcon top have polarity bits actually in tcon0 polarity
register.

Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
Reviewed-by: Chen-Yu Tsai 
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 25 +
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  6 ++
 2 files changed, 31 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 6b9af4c08cd6..9f06dec0fc61 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -672,6 +672,30 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
 SUN4I_TCON1_BASIC5_V_SYNC(vsync) |
 SUN4I_TCON1_BASIC5_H_SYNC(hsync));
 
+   /* Setup the polarity of multiple signals */
+   if (tcon->quirks->polarity_in_ch0) {
+   val = 0;
+
+   if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+   val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
+
+   if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+   val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
+
+   regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
+   } else {
+   /* according to vendor driver, this bit must be always set */
+   val = SUN4I_TCON1_IO_POL_UNKNOWN;
+
+   if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+   val |= SUN4I_TCON1_IO_POL_HSYNC_POSITIVE;
+
+   if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+   val |= SUN4I_TCON1_IO_POL_VSYNC_POSITIVE;
+
+   regmap_write(tcon->regs, SUN4I_TCON1_IO_POL_REG, val);
+   }
+
/* Map output pins to channel 1 */
regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
   SUN4I_TCON_GCTL_IOMAP_MASK,
@@ -1500,6 +1524,7 @@ static const struct sun4i_tcon_quirks 
sun8i_a83t_tv_quirks = {
 
 static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
.has_channel_1  = true,
+   .polarity_in_ch0= true,
.set_mux= sun8i_r40_tcon_tv_set_mux,
 };
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h 
b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index c5ac1b02482c..e624f6977eb8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -154,6 +154,11 @@
 #define SUN4I_TCON1_BASIC5_V_SYNC(height)  (((height) - 1) & 0x3ff)
 
 #define SUN4I_TCON1_IO_POL_REG 0xf0
+/* there is no documentation about this bit */
+#define SUN4I_TCON1_IO_POL_UNKNOWN BIT(26)
+#define SUN4I_TCON1_IO_POL_HSYNC_POSITIVE  BIT(25)
+#define SUN4I_TCON1_IO_POL_VSYNC_POSITIVE  BIT(24)
+
 #define SUN4I_TCON1_IO_TRI_REG 0xf4
 
 #define SUN4I_TCON_ECC_FIFO_REG0xf8
@@ -236,6 +241,7 @@ struct sun4i_tcon_quirks {
boolneeds_de_be_mux; /* sun6i needs mux to select backend */
boolneeds_edp_reset; /* a80 edp reset needed for tcon0 access */
boolsupports_lvds;   /* Does the TCON support an LVDS output? */
+   boolpolarity_in_ch0; /* some tcon1 channels have polarity bits in 
tcon0 pol register */
u8  dclk_min_div;   /* minimum divider for TCON0 DCLK */
 
/* callback to handle tcon muxing options */
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 1/5] clk: sunxi-ng: mp: fix parent rate change flag check

2021-02-08 Thread Jernej Skrabec
CLK_SET_RATE_PARENT flag is checked on parent clock instead of current
one. Fix that.

Fixes: 3f790433c3cb ("clk: sunxi-ng: Adjust MP clock parent rate when allowed")
Reviewed-by: Chen-Yu Tsai 
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/clk/sunxi-ng/ccu_mp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
index fa4ecb915590..5f40be6d2dfd 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -108,7 +108,7 @@ static unsigned long ccu_mp_round_rate(struct 
ccu_mux_internal *mux,
max_m = cmp->m.max ?: 1 << cmp->m.width;
max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
 
-   if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
+   if (!(clk_hw_get_flags(>common.hw) & CLK_SET_RATE_PARENT)) {
ccu_mp_find_best(*parent_rate, rate, max_m, max_p, , );
rate = *parent_rate / p / m;
} else {
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 0/5] sunxi: fix H6 HDMI related issues

2021-02-08 Thread Jernej Skrabec
Over the year I got plenty of reports of troubles with H6 HDMI signal.
Sometimes monitor flickers, sometimes there was no image at all and
sometimes it didn't play well with AVR.

It turns out there are multiple issues. Patch 1 fixes clock issue,
which didn't adjust parent rate, even if it is allowed to do so. Patch 2
adds polarity config in tcon1. This is seemingly not needed for pre-HDMI2
controllers, although BSP drivers set it accordingly every time. It
turns out that HDMI2 controllers often don't work with monitors if
polarity is not set correctly. Patch 3 always set clock rate for HDMI
controller. Patch 4 fixes H6 HDMI PHY setting. Patch 5 fixes comment and
clock rate limit (wrong reasoning).

Please take a look.

Best regards,
Jernej

Changes from v1:
- collected Chen-Yu tags (except on replaced patch 4)
- Added some comments in patch 2
- Replaced patch 4 (see commit log for explanation)

Jernej Skrabec (5):
  clk: sunxi-ng: mp: fix parent rate change flag check
  drm/sun4i: tcon: set sync polarity for tcon1 channel
  drm/sun4i: dw-hdmi: always set clock rate
  drm/sun4i: Fix H6 HDMI PHY configuration
  drm/sun4i: dw-hdmi: Fix max. frequency for H6

 drivers/clk/sunxi-ng/ccu_mp.c  |  2 +-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 25 +
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  6 ++
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c  | 10 +++---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |  1 -
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 26 +-
 6 files changed, 44 insertions(+), 26 deletions(-)

--
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 2/5] drm/sun4i: tcon: set sync polarity for tcon1 channel

2021-02-04 Thread Jernej Skrabec
Channel 1 has polarity bits for vsync and hsync signals but driver never
sets them. It turns out that with pre-HDMI2 controllers seemingly there
is no issue if polarity is not set. However, with HDMI2 controllers
(H6) there often comes to de-synchronization due to phase shift. This
causes flickering screen. It's safe to assume that similar issues might
happen also with pre-HDMI2 controllers.

Solve issue with setting vsync and hsync polarity. Note that display
stacks with tcon top have polarity bits actually in tcon0 polarity
register.

Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 24 
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  5 +
 2 files changed, 29 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 6b9af4c08cd6..0d132dae58c0 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -672,6 +672,29 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
 SUN4I_TCON1_BASIC5_V_SYNC(vsync) |
 SUN4I_TCON1_BASIC5_H_SYNC(hsync));
 
+   /* Setup the polarity of sync signals */
+   if (tcon->quirks->polarity_in_ch0) {
+   val = 0;
+
+   if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+   val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
+
+   if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+   val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
+
+   regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
+   } else {
+   val = SUN4I_TCON1_IO_POL_UNKNOWN;
+
+   if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+   val |= SUN4I_TCON1_IO_POL_HSYNC_POSITIVE;
+
+   if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+   val |= SUN4I_TCON1_IO_POL_VSYNC_POSITIVE;
+
+   regmap_write(tcon->regs, SUN4I_TCON1_IO_POL_REG, val);
+   }
+
/* Map output pins to channel 1 */
regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
   SUN4I_TCON_GCTL_IOMAP_MASK,
@@ -1500,6 +1523,7 @@ static const struct sun4i_tcon_quirks 
sun8i_a83t_tv_quirks = {
 
 static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
.has_channel_1  = true,
+   .polarity_in_ch0= true,
.set_mux= sun8i_r40_tcon_tv_set_mux,
 };
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h 
b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index c5ac1b02482c..b504fb2d3de5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -154,6 +154,10 @@
 #define SUN4I_TCON1_BASIC5_V_SYNC(height)  (((height) - 1) & 0x3ff)
 
 #define SUN4I_TCON1_IO_POL_REG 0xf0
+#define SUN4I_TCON1_IO_POL_UNKNOWN BIT(26)
+#define SUN4I_TCON1_IO_POL_HSYNC_POSITIVE  BIT(25)
+#define SUN4I_TCON1_IO_POL_VSYNC_POSITIVE  BIT(24)
+
 #define SUN4I_TCON1_IO_TRI_REG 0xf4
 
 #define SUN4I_TCON_ECC_FIFO_REG0xf8
@@ -236,6 +240,7 @@ struct sun4i_tcon_quirks {
boolneeds_de_be_mux; /* sun6i needs mux to select backend */
boolneeds_edp_reset; /* a80 edp reset needed for tcon0 access */
boolsupports_lvds;   /* Does the TCON support an LVDS output? */
+   boolpolarity_in_ch0; /* some tcon1 channels have polarity bits in 
tcon0 pol register */
u8  dclk_min_div;   /* minimum divider for TCON0 DCLK */
 
/* callback to handle tcon muxing options */
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 0/5] sunxi: fix H6 HDMI related issues

2021-02-04 Thread Jernej Skrabec
Over the year I got plenty of reports of troubles with H6 HDMI signal.
Sometimes monitor flickers, sometimes there was no image at all and
sometimes it didn't play well with AVR.

It turns out there are multiple issues. Patch 1 fixes clock issue,
which didn't adjust parent rate, even if it is allowed to do so. Patch 2
adds polarity config in tcon1. This is seemingly not needed for pre-HDMI2
controllers, although BSP drivers set it accordingly every time. It
turns out that HDMI2 controllers often don't work with monitors if
polarity is not set correctly. Patch 3 always set clock rate for HDMI
controller. Patch 4 fixes cpce PHY setting for 594 MHz. Patch 5 fixes
comment and clock rate limit (wrong reasoning).

Please take a look.

Best regards,
Jernej

Jernej Skrabec (5):
  clk: sunxi-ng: mp: fix parent rate change flag check
  drm/sun4i: tcon: set sync polarity for tcon1 channel
  drm/sun4i: dw-hdmi: always set clock rate
  drm/sun4i: Fix H6 HDMI PHY configuration
  drm/sun4i: dw-hdmi: Fix max. frequency for H6

 drivers/clk/sunxi-ng/ccu_mp.c  |  2 +-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 24 
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  5 +
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c  | 10 +++---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |  1 -
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c |  2 +-
 6 files changed, 34 insertions(+), 10 deletions(-)

-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 1/5] clk: sunxi-ng: mp: fix parent rate change flag check

2021-02-04 Thread Jernej Skrabec
CLK_SET_RATE_PARENT flag is checked on parent clock instead of current
one. Fix that.

Fixes: 3f790433c3cb ("clk: sunxi-ng: Adjust MP clock parent rate when allowed")
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/clk/sunxi-ng/ccu_mp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
index fa4ecb915590..5f40be6d2dfd 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -108,7 +108,7 @@ static unsigned long ccu_mp_round_rate(struct 
ccu_mux_internal *mux,
max_m = cmp->m.max ?: 1 << cmp->m.width;
max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
 
-   if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
+   if (!(clk_hw_get_flags(>common.hw) & CLK_SET_RATE_PARENT)) {
ccu_mp_find_best(*parent_rate, rate, max_m, max_p, , );
rate = *parent_rate / p / m;
} else {
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 4/5] drm/sun4i: Fix H6 HDMI PHY configuration

2021-02-04 Thread Jernej Skrabec
cpce value for 594 MHz is set differently in BSP driver. Fix that.

Fixes: c71c9b2fee17 ("drm/sun4i: Add support for Synopsys HDMI PHY")
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 35c2133724e2..89aff19ddeb4 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -89,7 +89,7 @@ static const struct dw_hdmi_mpll_config sun50i_h6_mpll_cfg[] 
= {
},
},  {
59400, {
-   { 0x1a40, 0x0003 },
+   { 0x1a7c, 0x0003 },
{ 0x3b4c, 0x0003 },
{ 0x5a64, 0x0003 },
},
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 3/5] drm/sun4i: dw-hdmi: always set clock rate

2021-02-04 Thread Jernej Skrabec
As expected, HDMI controller clock should always match pixel clock. In
the past, changing HDMI controller rate would seemingly worsen
situation. However, that was the result of other bugs which are now
fixed.

Fix that by removing set_rate quirk and always set clock rate.

Fixes: 40bb9d3147b2 ("drm/sun4i: Add support for H6 DW HDMI controller")
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 4 +---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 1 -
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 92add2cef2e7..23773a5e0650 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -21,8 +21,7 @@ static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder 
*encoder,
 {
struct sun8i_dw_hdmi *hdmi = encoder_to_sun8i_dw_hdmi(encoder);
 
-   if (hdmi->quirks->set_rate)
-   clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000);
+   clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000);
 }
 
 static const struct drm_encoder_helper_funcs
@@ -295,7 +294,6 @@ static int sun8i_dw_hdmi_remove(struct platform_device 
*pdev)
 
 static const struct sun8i_dw_hdmi_quirks sun8i_a83t_quirks = {
.mode_valid = sun8i_dw_hdmi_mode_valid_a83t,
-   .set_rate = true,
 };
 
 static const struct sun8i_dw_hdmi_quirks sun50i_h6_quirks = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index d983746fa194..d4b55af0592f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -179,7 +179,6 @@ struct sun8i_dw_hdmi_quirks {
enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data,
   const struct drm_display_info *info,
   const struct drm_display_mode *mode);
-   unsigned int set_rate : 1;
unsigned int use_drm_infoframe : 1;
 };
 
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 5/5] drm/sun4i: dw-hdmi: Fix max. frequency for H6

2021-02-04 Thread Jernej Skrabec
It turns out that reasoning for lowering max. supported frequency is
wrong. Scrambling works just fine. Several now fixed bugs prevented
proper functioning, even with rates lower than 340 MHz. Issues were just
more pronounced with higher frequencies.

Fix that by allowing max. supported frequency in HW and fix the comment.

Fixes: cd9063757a22 ("drm/sun4i: DW HDMI: Lower max. supported rate for H6")
Tested-by: Andre Heider 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 23773a5e0650..bbdfd5e26ec8 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -47,11 +47,9 @@ sun8i_dw_hdmi_mode_valid_h6(struct dw_hdmi *hdmi, void *data,
 {
/*
 * Controller support maximum of 594 MHz, which correlates to
-* 4K@60Hz 4:4:4 or RGB. However, for frequencies greater than
-* 340 MHz scrambling has to be enabled. Because scrambling is
-* not yet implemented, just limit to 340 MHz for now.
+* 4K@60Hz 4:4:4 or RGB.
 */
-   if (mode->clock > 34)
+   if (mode->clock > 594000)
return MODE_CLOCK_HIGH;
 
return MODE_OK;
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 3/3] drm/sun4i: Add support for BT2020 to DE3

2021-01-11 Thread Jernej Skrabec
DE3 supports 10-bit formats, so it's only naturally to also support
BT2020 encoding.

Add support for it.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_csc.c  | 12 +++-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c |  2 ++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c 
b/drivers/gpu/drm/sun4i/sun8i_csc.c
index 1d10714e417e..9bd62de0c288 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
@@ -69,7 +69,7 @@ static const u32 yuv2rgb[2][2][12] = {
  * c20 c21 c22 [d2 const2]
  */
 
-static const u32 yuv2rgb_de3[2][2][12] = {
+static const u32 yuv2rgb_de3[2][3][12] = {
[DRM_COLOR_YCBCR_LIMITED_RANGE] = {
[DRM_COLOR_YCBCR_BT601] = {
0x0002542A, 0x, 0x0003312A, 0xFFC0,
@@ -80,6 +80,11 @@ static const u32 yuv2rgb_de3[2][2][12] = {
0x0002542A, 0x, 0x000395E2, 0xFFC0,
0x0002542A, 0x92D2, 0xFFFEEF27, 0xFE00,
0x0002542A, 0x0004398C, 0x, 0xFE00,
+   },
+   [DRM_COLOR_YCBCR_BT2020] = {
+   0x0002542A, 0x, 0x00035B7B, 0xFFC0,
+   0x0002542A, 0xA017, 0xFFFEB2FC, 0xFE00,
+   0x0002542A, 0x00044896, 0x, 0xFE00,
}
},
[DRM_COLOR_YCBCR_FULL_RANGE] = {
@@ -92,6 +97,11 @@ static const u32 yuv2rgb_de3[2][2][12] = {
0x0002, 0x, 0x0003264C, 0x,
0x0002, 0xA018, 0x1053, 0xFE00,
0x0002, 0x0003B611, 0x, 0xFE00,
+   },
+   [DRM_COLOR_YCBCR_BT2020] = {
+   0x0002, 0x, 0x0002F2FE, 0x,
+   0x0002, 0xABC0, 0xFFFEDB78, 0xFE00,
+   0x0002, 0x0003C346, 0x, 0xFE00,
}
},
 };
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 76393fc976fe..8cc294a9969d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -543,6 +543,8 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct 
drm_device *drm,
 
supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
  BIT(DRM_COLOR_YCBCR_BT709);
+   if (mixer->cfg->is_de3)
+   supported_encodings |= BIT(DRM_COLOR_YCBCR_BT2020);
 
supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
   BIT(DRM_COLOR_YCBCR_FULL_RANGE);
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 0/3] drm/sun4i: de2/de3: CSC improvements

2021-01-11 Thread Jernej Skrabec
This short series reworks CSC handling to remove duplicated constants
(patch 1 and 2) and adds BT2020 encoding to DE3 (patch 3).

Please take a look.

Best regards,
Jernej

Jernej Skrabec (3):
  drm/sun4i: csc: Rework DE3 CSC macros
  drm/sun4i: de2/de3: Remove redundant CSC matrices
  drm/sun4i: Add support for BT2020 to DE3

 drivers/gpu/drm/sun4i/sun8i_csc.c  | 109 ++---
 drivers/gpu/drm/sun4i/sun8i_mixer.h|   6 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c |   2 +
 3 files changed, 48 insertions(+), 69 deletions(-)

-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 1/3] drm/sun4i: csc: Rework DE3 CSC macros

2021-01-11 Thread Jernej Skrabec
Rework DE3 CSC macros to take just one coordinate instead of two. This
will make its usage easier in subsequent commit.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_csc.c   | 2 +-
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 6 ++
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c 
b/drivers/gpu/drm/sun4i/sun8i_csc.c
index 781955dd4995..5c6ad643dae2 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
@@ -194,7 +194,7 @@ static void sun8i_de3_ccsc_set_coefficients(struct regmap 
*map, int layer,
return;
}
 
-   base_reg = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0, 0);
+   base_reg = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0);
regmap_bulk_write(map, base_reg, table, 12);
 }
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h 
b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 7576b523fdbb..145833a9d82d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -50,10 +50,8 @@
 #define SUN8I_MIXER_BLEND_CK_MIN(base, x)  ((base) + 0xe0 + 0x04 * (x))
 #define SUN8I_MIXER_BLEND_OUTCTL(base) ((base) + 0xfc)
 #define SUN50I_MIXER_BLEND_CSC_CTL(base)   ((base) + 0x100)
-#define SUN50I_MIXER_BLEND_CSC_COEFF(base, layer, x, y) \
-   ((base) + 0x110 + (layer) * 0x30 +  (x) * 0x10 + 4 * (y))
-#define SUN50I_MIXER_BLEND_CSC_CONST(base, layer, i) \
-   ((base) + 0x110 + (layer) * 0x30 +  (i) * 0x10 + 0x0c)
+#define SUN50I_MIXER_BLEND_CSC_COEFF(base, layer, x) \
+   ((base) + 0x110 + (layer) * 0x30 +  (x) * 4)
 
 #define SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK  GENMASK(12, 8)
 #define SUN8I_MIXER_BLEND_PIPE_CTL_EN(pipe)BIT(8 + pipe)
-- 
2.30.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 2/3] drm/sun4i: de2/de3: Remove redundant CSC matrices

2021-01-11 Thread Jernej Skrabec
YUV to RGB matrices are almost identical to YVU to RGB matrices. They
only have second and third column reversed. Do that reversion in code in
order to lower amount of static data and redundancy.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_csc.c | 99 +++
 1 file changed, 34 insertions(+), 65 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c 
b/drivers/gpu/drm/sun4i/sun8i_csc.c
index 5c6ad643dae2..1d10714e417e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
@@ -46,33 +46,6 @@ static const u32 yuv2rgb[2][2][12] = {
},
 };
 
-static const u32 yvu2rgb[2][2][12] = {
-   [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
-   [DRM_COLOR_YCBCR_BT601] = {
-   0x04A8, 0x0662, 0x, 0xFFFC8451,
-   0x04A8, 0xFCC0, 0xFE6F, 0x00021E4D,
-   0x04A8, 0x, 0x0811, 0xFFFBACA9,
-   },
-   [DRM_COLOR_YCBCR_BT709] = {
-   0x04A8, 0x072B, 0x, 0xFFFC1F99,
-   0x04A8, 0xFDDF, 0xFF26, 0x00013383,
-   0x04A8, 0x, 0x0873, 0xFFFB7BEF,
-   }
-   },
-   [DRM_COLOR_YCBCR_FULL_RANGE] = {
-   [DRM_COLOR_YCBCR_BT601] = {
-   0x0400, 0x059B, 0x, 0xFFFD322E,
-   0x0400, 0xFD25, 0xFEA0, 0x00021DD5,
-   0x0400, 0x, 0x0716, 0xFFFC74BD,
-   },
-   [DRM_COLOR_YCBCR_BT709] = {
-   0x0400, 0x064C, 0x, 0xFFFCD9B4,
-   0x0400, 0xFE21, 0xFF41, 0x00014F96,
-   0x0400, 0x, 0x076C, 0xFFFC49EF,
-   }
-   },
-};
-
 /*
  * DE3 has a bit different CSC units. Factors are in two's complement format.
  * First three factors in a row are multiplication factors which have 17 bits
@@ -123,33 +96,6 @@ static const u32 yuv2rgb_de3[2][2][12] = {
},
 };
 
-static const u32 yvu2rgb_de3[2][2][12] = {
-   [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
-   [DRM_COLOR_YCBCR_BT601] = {
-   0x0002542A, 0x0003312A, 0x, 0xFFC0,
-   0x0002542A, 0xFFFE5FC3, 0x376B, 0xFE00,
-   0x0002542A, 0x, 0x000408D2, 0xFE00,
-   },
-   [DRM_COLOR_YCBCR_BT709] = {
-   0x0002542A, 0x000395E2, 0x, 0xFFC0,
-   0x0002542A, 0xFFFEEF27, 0x92D2, 0xFE00,
-   0x0002542A, 0x, 0x0004398C, 0xFE00,
-   }
-   },
-   [DRM_COLOR_YCBCR_FULL_RANGE] = {
-   [DRM_COLOR_YCBCR_BT601] = {
-   0x0002, 0x0002CDD2, 0x, 0x,
-   0x0002, 0xFFFE925D, 0x4FCE, 0xFE00,
-   0x0002, 0x, 0x00038B43, 0xFE00,
-   },
-   [DRM_COLOR_YCBCR_BT709] = {
-   0x0002, 0x0003264C, 0x, 0x,
-   0x0002, 0x1053, 0xA018, 0xFE00,
-   0x0002, 0x, 0x0003B611, 0xFE00,
-   }
-   },
-};
-
 static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
   enum sun8i_csc_mode mode,
   enum drm_color_encoding encoding,
@@ -157,21 +103,30 @@ static void sun8i_csc_set_coefficients(struct regmap 
*map, u32 base,
 {
const u32 *table;
u32 base_reg;
+   int i;
+
+   table = yuv2rgb[range][encoding];
 
switch (mode) {
case SUN8I_CSC_MODE_YUV2RGB:
-   table = yuv2rgb[range][encoding];
+   base_reg = SUN8I_CSC_COEFF(base, 0);
+   regmap_bulk_write(map, base_reg, table, 12);
break;
case SUN8I_CSC_MODE_YVU2RGB:
-   table = yvu2rgb[range][encoding];
+   for (i = 0; i < 12; i++) {
+   if ((i & 3) == 1)
+   base_reg = SUN8I_CSC_COEFF(base, i + 1);
+   else if ((i & 3) == 2)
+   base_reg = SUN8I_CSC_COEFF(base, i - 1);
+   else
+   base_reg = SUN8I_CSC_COEFF(base, i);
+   regmap_write(map, base_reg, table[i]);
+   }
break;
default:
DRM_WARN("Wrong CSC mode specified.\n");
return;
}
-
-   base_reg = SUN8I_CSC_COEFF(base, 0);
-   regmap_bulk_write(map, base_reg, table, 12);
 }
 
 static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer,
@@ -180,22 +135,36 @@ static void sun8i_de3_

[PATCH v3] drm/sun4i: de2: Reimplement plane z position setting logic

2021-01-07 Thread Jernej Skrabec
From: Roman Stratiienko 

To set blending channel order register software needs to know state and
position of each channel, which impossible at plane commit stage.

Move this procedure to atomic_flush stage, where all necessary information
is available.

Fixes: f88c5ee77496 ("drm/sun4i: Implement zpos for DE2")
Fixes: d8b3f454dab4 ("drm/sun4i: sun8i: Avoid clearing blending order at each 
atomic commit")
Signed-off-by: Roman Stratiienko 
[rebased, addressed comments]
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c| 57 +-
 drivers/gpu/drm/sun4i/sun8i_mixer.h|  5 +++
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 42 +++
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 42 +++
 4 files changed, 64 insertions(+), 82 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 5b42cf25cc86..d2153b10b08d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -250,6 +250,50 @@ int sun8i_mixer_drm_format_to_hw(u32 format, u32 
*hw_format)
 
 static void sun8i_mixer_commit(struct sunxi_engine *engine)
 {
+   struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
+   int channel_by_zpos[SUN8I_MIXER_MAX_CHANNELS];
+   u32 base = sun8i_blender_base(mixer);
+   u32 route = 0, pipe_ctl = 0;
+   unsigned int channel_count;
+   int i, j;
+
+   channel_count = mixer->cfg->vi_num + mixer->cfg->ui_num;
+
+   DRM_DEBUG_DRIVER("Update blender routing\n");
+
+   for (i = 0; i < SUN8I_MIXER_MAX_CHANNELS; i++)
+   channel_by_zpos[i] = -1;
+
+   for (i = 0; i < channel_count; i++) {
+   int zpos = mixer->channel_zpos[i];
+
+   if (zpos >= 0 && zpos < channel_count)
+   channel_by_zpos[zpos] = i;
+   }
+
+   j = 0;
+   for (i = 0; i < channel_count; i++) {
+   int ch = channel_by_zpos[i];
+
+   if (ch >= 0) {
+   pipe_ctl |= SUN8I_MIXER_BLEND_PIPE_CTL_EN(j);
+   route |= ch << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(j);
+   j++;
+   }
+   }
+
+   /*
+* Set fill color of bottom plane to black. Generally not needed
+* except when VI plane is at bottom (zpos = 0) and enabled.
+*/
+   pipe_ctl |= SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0);
+
+   regmap_write(mixer->engine.regs,
+SUN8I_MIXER_BLEND_PIPE_CTL(base), pipe_ctl);
+
+   regmap_write(mixer->engine.regs,
+SUN8I_MIXER_BLEND_ROUTE(base), route);
+
DRM_DEBUG_DRIVER("Committing changes\n");
 
regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF,
@@ -479,23 +523,16 @@ static int sun8i_mixer_bind(struct device *dev, struct 
device *master,
regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
 SUN8I_MIXER_BLEND_COLOR_BLACK);
 
-   /*
-* Set fill color of bottom plane to black. Generally not needed
-* except when VI plane is at bottom (zpos = 0) and enabled.
-*/
-   regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
-SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
 SUN8I_MIXER_BLEND_COLOR_BLACK);
 
plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
-   for (i = 0; i < plane_cnt; i++)
+   for (i = 0; i < plane_cnt; i++) {
+   mixer->channel_zpos[i] = -1;
regmap_write(mixer->engine.regs,
 SUN8I_MIXER_BLEND_MODE(base, i),
 SUN8I_MIXER_BLEND_MODE_DEF);
-
-   regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
-  SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
+   }
 
return 0;
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h 
b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 7576b523fdbb..7b378d6e4dd9 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -12,6 +12,8 @@
 
 #include "sunxi_engine.h"
 
+#define SUN8I_MIXER_MAX_CHANNELS   5
+
 #define SUN8I_MIXER_SIZE(w, h) (((h) - 1) << 16 | ((w) - 1))
 #define SUN8I_MIXER_COORD(x, y)((y) << 16 | (x))
 
@@ -179,6 +181,9 @@ struct sun8i_mixer {
 
struct clk  *bus_clk;
struct clk  *mod_clk;
+
+   /* -1 means that layer is disabled */
+   int channel_zpos[SUN8I_MIXER_MAX_CHANNELS];
 };
 
 static inline struct sun8i_mixer *
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 816ad4ce8996..9f82

[PATCH] drm/sun4i: Fix DE2 YVU handling

2020-09-02 Thread Jernej Skrabec
Function sun8i_vi_layer_get_csc_mode() is supposed to return CSC mode
but due to inproper return type (bool instead of u32) it returns just 0
or 1. Colors are wrong for YVU formats because of that.

Fixes: daab3d0e8e2b ("drm/sun4i: de2: csc_mode in de2 format struct is mostly 
redundant")
Reported-by: Roman Stratiienko 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 22c8c5375d0d..c0147af6a840 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -211,7 +211,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer 
*mixer, int channel,
return 0;
 }
 
-static bool sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format)
+static u32 sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format)
 {
if (!format->is_yuv)
return SUN8I_CSC_MODE_OFF;
-- 
2.28.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 1/2] dt-bindings: gpu: mali-utgard: Add Allwinner R40 compatible

2020-08-25 Thread Jernej Skrabec
Allwinner R40 SoC contains Mali400, so add its specific compatible to
bindings.

Signed-off-by: Jernej Skrabec 
---
 Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml 
b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml
index 6226d31ec4b7..d4d785790eaa 100644
--- a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml
+++ b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml
@@ -25,6 +25,7 @@ properties:
   - allwinner,sun4i-a10-mali
   - allwinner,sun7i-a20-mali
   - allwinner,sun8i-h3-mali
+  - allwinner,sun8i-r40-mali
   - allwinner,sun50i-a64-mali
   - rockchip,rk3036-mali
   - rockchip,rk3066-mali
@@ -129,6 +130,7 @@ allOf:
 enum:
   - allwinner,sun4i-a10-mali
   - allwinner,sun7i-a20-mali
+  - allwinner,sun8i-r40-mali
   - allwinner,sun50i-a64-mali
   - allwinner,sun50i-h5-mali
   - amlogic,meson8-mali
-- 
2.28.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 2/2] ARM: dts: sun8i: r40: Add Mali node

2020-08-25 Thread Jernej Skrabec
R40 has Mali400 GP2 GPU. Add a node for it.

Signed-off-by: Jernej Skrabec 
---
 arch/arm/boot/dts/sun8i-r40.dtsi | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index b782041e0e04..b82031b19893 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -743,6 +743,28 @@ i2c4: i2c@1c2c000 {
#size-cells = <0>;
};
 
+   mali: gpu@1c4 {
+   compatible = "allwinner,sun8i-r40-mali", "arm,mali-400";
+   reg = <0x01c4 0x1>;
+   interrupts = ,
+,
+,
+,
+,
+,
+;
+   interrupt-names = "gp",
+ "gpmmu",
+ "pp0",
+ "ppmmu0",
+ "pp1",
+ "ppmmu1",
+ "pmu";
+   clocks = < CLK_BUS_GPU>, < CLK_GPU>;
+   clock-names = "bus", "core";
+   resets = < RST_BUS_GPU>;
+   };
+
gmac: ethernet@1c5 {
compatible = "allwinner,sun8i-r40-gmac";
syscon = <>;
-- 
2.28.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 0/2] ARM: dts: sun8i: r40: Enable mali400 GPU

2020-08-25 Thread Jernej Skrabec
Following two patches enable Mali400 GPU on Allwinner R40 SoC. At this
point I didn't add table for frequency switching because it would
require far more testing and defaults work stable and reasonably well.

Please take a look.

Best regards,
Jernej

Jernej Skrabec (2):
  dt-bindings: gpu: mali-utgard: Add Allwinner R40 compatible
  ARM: dts: sun8i: r40: Add Mali node

 .../bindings/gpu/arm,mali-utgard.yaml |  2 ++
 arch/arm/boot/dts/sun8i-r40.dtsi  | 22 +++
 2 files changed, 24 insertions(+)

-- 
2.28.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/sun4i: mixer: Enable register value caching

2020-07-26 Thread Jernej Skrabec
It was discovered in the past by Ondrej Jirman that mixer register read
may occasionally return wrong value, most likely zero. It turns out
that all mixer units are affected by this issue. This becomes especially
obvious with applications like video player. After a few minutes of a
playback visual glitches appeared but not always in the same way. After
register inspection it was clear that some bits are not set even when
they should be.

Best solution would be to shuffle the code a bit to avoid
read-modify-write operations and use only register writes. However,
quicker solution is to enable caching support in regmap which is also
used here. Such fix is also easier to backport in stable kernels.

Fixes: 9d75b8c0b999 ("drm/sun4i: add support for Allwinner DE2 mixers")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index cc4fb916318f..f8f17c51c96d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -303,11 +303,23 @@ static const struct sunxi_engine_ops sun8i_engine_ops = {
.layers_init= sun8i_layers_init,
 };
 
+static bool sun8i_mixer_volatile_reg(struct device *dev, unsigned int reg)
+{
+   switch (reg) {
+   case SUN8I_MIXER_GLOBAL_STATUS:
+   case SUN8I_MIXER_GLOBAL_DBUFF:
+   return true;
+   }
+   return false;
+}
+
 static struct regmap_config sun8i_mixer_regmap_config = {
+   .cache_type = REGCACHE_FLAT,
.reg_bits   = 32,
.val_bits   = 32,
.reg_stride = 4,
.max_register   = 0xbfffc, /* guessed */
+   .volatile_reg   = sun8i_mixer_volatile_reg,
 };
 
 static int sun8i_mixer_of_get_id(struct device_node *node)
-- 
2.27.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/sun4i: hdmi ddc clk: Fix size of m divider

2020-04-14 Thread Jernej Skrabec
m divider in DDC clock register is 4 bits wide. Fix that.

Fixes: 9c5681011a0c ("drm/sun4i: Add HDMI support")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun4i_hdmi.h | 2 +-
 drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi.h 
b/drivers/gpu/drm/sun4i/sun4i_hdmi.h
index 7ad3f06c127e..00ca35f07ba5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi.h
@@ -148,7 +148,7 @@
 #define SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE  3
 
 #define SUN4I_HDMI_DDC_CLK_REG 0x528
-#define SUN4I_HDMI_DDC_CLK_M(m)(((m) & 0x7) << 3)
+#define SUN4I_HDMI_DDC_CLK_M(m)(((m) & 0xf) << 3)
 #define SUN4I_HDMI_DDC_CLK_N(n)((n) & 0x7)
 
 #define SUN4I_HDMI_DDC_LINE_CTRL_REG   0x540
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c 
b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
index 2ff780114106..12430b9d4e93 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
@@ -33,7 +33,7 @@ static unsigned long sun4i_ddc_calc_divider(unsigned long 
rate,
unsigned long best_rate = 0;
u8 best_m = 0, best_n = 0, _m, _n;
 
-   for (_m = 0; _m < 8; _m++) {
+   for (_m = 0; _m < 16; _m++) {
for (_n = 0; _n < 8; _n++) {
unsigned long tmp_rate;
 
-- 
2.26.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 1/4] drm/bridge: dw-hdmi: fix AVI frame colorimetry

2020-03-05 Thread Jernej Skrabec
CTA-861-F explicitly states that for RGB colorspace colorimetry should
be set to "none". Fix that.

Acked-by: Laurent Pinchart 
Fixes: def23aa7e982 ("drm: bridge: dw-hdmi: Switch to V4L bus format and 
encodings")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 46 +--
 1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 67fca439bbfb..24965e53d351 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1624,28 +1624,34 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, 
struct drm_display_mode *mode)
frame.colorspace = HDMI_COLORSPACE_RGB;
 
/* Set up colorimetry */
-   switch (hdmi->hdmi_data.enc_out_encoding) {
-   case V4L2_YCBCR_ENC_601:
-   if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
-   frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
-   else
+   if (!hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
+   switch (hdmi->hdmi_data.enc_out_encoding) {
+   case V4L2_YCBCR_ENC_601:
+   if (hdmi->hdmi_data.enc_in_encoding == 
V4L2_YCBCR_ENC_XV601)
+   frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
+   else
+   frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
+   frame.extended_colorimetry =
+   HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+   break;
+   case V4L2_YCBCR_ENC_709:
+   if (hdmi->hdmi_data.enc_in_encoding == 
V4L2_YCBCR_ENC_XV709)
+   frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
+   else
+   frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
+   frame.extended_colorimetry =
+   HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
+   break;
+   default: /* Carries no data */
frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
+   frame.extended_colorimetry =
+   HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+   break;
+   }
+   } else {
+   frame.colorimetry = HDMI_COLORIMETRY_NONE;
frame.extended_colorimetry =
-   HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-   break;
-   case V4L2_YCBCR_ENC_709:
-   if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
-   frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
-   else
-   frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
-   frame.extended_colorimetry =
-   HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
-   break;
-   default: /* Carries no data */
-   frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
-   frame.extended_colorimetry =
-   HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-   break;
+   HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
}
 
frame.scan_mode = HDMI_SCAN_MODE_NONE;
-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 0/4] drm/bridge: dw-hdmi: Various updates

2020-03-05 Thread Jernej Skrabec
This series fixes multiple issues I found out.
Patch 1 fixes reporting colorimetry in AVI frame.
Patch 2 sets scan mode to underscan which is in line with most other
hdmi drivers.
Patch 3 aligns RGB quantization to CEA 861 standard.
Patch 4 reworks is_color_space_conversion(). Now it checks only if
color space conversion is required. Patch adds separate function for
checking if any kind of conversion is required.

Please take a look.

Best regards,
Jernej

Changes from v2:
- added tags
- replaced patch 2 with patch 4
- renamed rgb conversion matrix and make hex lowercase
- move logic for checking if rgb full to limited range conversion is
  needed to is_color_space_conversion()
- reworked logic for csc matrix selection

Jernej Skrabec (3):
  drm/bridge: dw-hdmi: fix AVI frame colorimetry
  drm/bridge: dw-hdmi: Add support for RGB limited range
  drm/bridge: dw-hdmi: rework csc related functions

Jonas Karlman (1):
  drm/bridge: dw-hdmi: do not force "none" scan mode

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 132 ++
 1 file changed, 88 insertions(+), 44 deletions(-)

-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 3/4] drm/bridge: dw-hdmi: Add support for RGB limited range

2020-03-05 Thread Jernej Skrabec
CEA 861 standard requestis that RGB quantization range is "limited" for
CEA modes. Support that by adding CSC matrix which downscales values.

This allows proper color reproduction on TV and PC monitor at the same
time. In future, override property can be added, like "Broadcast RGB"
in i915 driver.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 63 +--
 1 file changed, 46 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index de2c7ec887c8..c8a02e5b5e1b 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -92,6 +92,12 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
{ 0x6756, 0x78ab, 0x2000, 0x0200 }
 };
 
+static const u16 csc_coeff_rgb_full_to_rgb_limited[3][4] = {
+   { 0x1b7c, 0x, 0x, 0x0020 },
+   { 0x, 0x1b7c, 0x, 0x0020 },
+   { 0x, 0x, 0x1b7c, 0x0020 }
+};
+
 struct hdmi_vmode {
bool mdataenablepolarity;
 
@@ -109,6 +115,7 @@ struct hdmi_data_info {
unsigned int pix_repet_factor;
unsigned int hdcp_enable;
struct hdmi_vmode video_mode;
+   bool rgb_limited_range;
 };
 
 struct dw_hdmi_i2c {
@@ -956,7 +963,11 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
 
 static int is_color_space_conversion(struct dw_hdmi *hdmi)
 {
-   return hdmi->hdmi_data.enc_in_bus_format != 
hdmi->hdmi_data.enc_out_bus_format;
+   return (hdmi->hdmi_data.enc_in_bus_format !=
+   hdmi->hdmi_data.enc_out_bus_format) ||
+  (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) &&
+   hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) &&
+   hdmi->hdmi_data.rgb_limited_range);
 }
 
 static int is_color_space_decimation(struct dw_hdmi *hdmi)
@@ -986,25 +997,27 @@ static int is_color_space_interpolation(struct dw_hdmi 
*hdmi)
 static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
 {
const u16 (*csc_coeff)[3][4] = _coeff_default;
+   bool is_input_rgb, is_output_rgb;
unsigned i;
u32 csc_scale = 1;
 
-   if (is_color_space_conversion(hdmi)) {
-   if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
-   if (hdmi->hdmi_data.enc_out_encoding ==
-   V4L2_YCBCR_ENC_601)
-   csc_coeff = _coeff_rgb_out_eitu601;
-   else
-   csc_coeff = _coeff_rgb_out_eitu709;
-   } else if (hdmi_bus_fmt_is_rgb(
-   hdmi->hdmi_data.enc_in_bus_format)) {
-   if (hdmi->hdmi_data.enc_out_encoding ==
-   V4L2_YCBCR_ENC_601)
-   csc_coeff = _coeff_rgb_in_eitu601;
-   else
-   csc_coeff = _coeff_rgb_in_eitu709;
-   csc_scale = 0;
-   }
+   is_input_rgb = hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format);
+   is_output_rgb = hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format);
+
+   if (!is_input_rgb && is_output_rgb) {
+   if (hdmi->hdmi_data.enc_out_encoding == V4L2_YCBCR_ENC_601)
+   csc_coeff = _coeff_rgb_out_eitu601;
+   else
+   csc_coeff = _coeff_rgb_out_eitu709;
+   } else if (is_input_rgb && !is_output_rgb) {
+   if (hdmi->hdmi_data.enc_out_encoding == V4L2_YCBCR_ENC_601)
+   csc_coeff = _coeff_rgb_in_eitu601;
+   else
+   csc_coeff = _coeff_rgb_in_eitu709;
+   csc_scale = 0;
+   } else if (is_input_rgb && is_output_rgb &&
+  hdmi->hdmi_data.rgb_limited_range) {
+   csc_coeff = _coeff_rgb_full_to_rgb_limited;
}
 
/* The CSC registers are sequential, alternating MSB then LSB */
@@ -1614,6 +1627,18 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct 
drm_display_mode *mode)
drm_hdmi_avi_infoframe_from_display_mode(,
 >connector, mode);
 
+   if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
+   drm_hdmi_avi_infoframe_quant_range(, >connector,
+  mode,
+  
hdmi->hdmi_data.rgb_limited_range ?
+  
HDMI_QUANTIZATION_RANGE_LIMITED :
+  
HDMI_QUANTIZATION_RANGE_FULL);
+   } else {
+   frame.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
+   frame.ycc_quant

[PATCH v2 2/4] drm/bridge: dw-hdmi: do not force "none" scan mode

2020-03-05 Thread Jernej Skrabec
From: Jonas Karlman 

Setting scan mode to "none" confuses some TVs like LG B8, which randomly
change overscan percentage over time. Digital outputs like HDMI and DVI,
handled by this controller, don't really need overscan, so we can always
set scan mode to underscan. Actually, this is exactly what
drm_hdmi_avi_infoframe_from_display_mode() already does, so we can just
remove offending line.

Reviewed-by: Neil Armstrong 
Acked-by: Laurent Pinchart 
Signed-off-by: Jonas Karlman 
[updated commit message]
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 24965e53d351..de2c7ec887c8 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1654,8 +1654,6 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct 
drm_display_mode *mode)
HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
}
 
-   frame.scan_mode = HDMI_SCAN_MODE_NONE;
-
/*
 * The Designware IP uses a different byte format from standard
 * AVI info frames, though generally the bits are in the correct
-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 4/4] drm/bridge: dw-hdmi: rework csc related functions

2020-03-05 Thread Jernej Skrabec
is_color_space_conversion() is a misnomer. It checks not only if color
space conversion is needed, but also if format conversion is needed.
This is actually desired behaviour because result of this function
determines if CSC block should be enabled or not (CSC block can also do
format conversion).

In order to clear misunderstandings, let's rework
is_color_space_conversion() to do exactly what is supposed to do and add
another function which will determine if CSC block must be enabled or
not.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 31 +++
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index c8a02e5b5e1b..7724191e0a8b 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -963,11 +963,14 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
 
 static int is_color_space_conversion(struct dw_hdmi *hdmi)
 {
-   return (hdmi->hdmi_data.enc_in_bus_format !=
-   hdmi->hdmi_data.enc_out_bus_format) ||
-  (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) &&
-   hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) &&
-   hdmi->hdmi_data.rgb_limited_range);
+   struct hdmi_data_info *hdmi_data = >hdmi_data;
+   bool is_input_rgb, is_output_rgb;
+
+   is_input_rgb = hdmi_bus_fmt_is_rgb(hdmi_data->enc_in_bus_format);
+   is_output_rgb = hdmi_bus_fmt_is_rgb(hdmi_data->enc_out_bus_format);
+
+   return (is_input_rgb != is_output_rgb) ||
+  (is_input_rgb && is_output_rgb && hdmi_data->rgb_limited_range);
 }
 
 static int is_color_space_decimation(struct dw_hdmi *hdmi)
@@ -994,6 +997,13 @@ static int is_color_space_interpolation(struct dw_hdmi 
*hdmi)
return 0;
 }
 
+static bool is_conversion_needed(struct dw_hdmi *hdmi)
+{
+   return is_color_space_conversion(hdmi) ||
+  is_color_space_decimation(hdmi) ||
+  is_color_space_interpolation(hdmi);
+}
+
 static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
 {
const u16 (*csc_coeff)[3][4] = _coeff_default;
@@ -2014,18 +2024,19 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi 
*hdmi)
hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
 
/* Enable csc path */
-   if (is_color_space_conversion(hdmi)) {
+   if (is_conversion_needed(hdmi)) {
hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
-   }
 
-   /* Enable color space conversion if needed */
-   if (is_color_space_conversion(hdmi))
hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
HDMI_MC_FLOWCTRL);
-   else
+   } else {
+   hdmi->mc_clkdis |= HDMI_MC_CLKDIS_CSCCLK_DISABLE;
+   hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+
hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
HDMI_MC_FLOWCTRL);
+   }
 }
 
 /* Workaround to clear the overflow condition */
-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 4/4] drm/bridge: dw-hdmi: Add support for RGB limited range

2020-03-02 Thread Jernej Skrabec
CEA 861 standard request that RGB quantization range is "limited" for
CEA modes. Support that by adding CSC matrix which downscales values.

This allows to proper color reproduction on TV and PC monitor at the
same time. In future, override property can be added, like "Broadcast
RGB" in i915 driver.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 36 +--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 3d6021119942..101c90156fa0 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -92,6 +92,12 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
{ 0x6756, 0x78ab, 0x2000, 0x0200 }
 };
 
+static const u16 csc_coeff_rgb_limited[3][4] = {
+   { 0x1B7C, 0x, 0x, 0x0020 },
+   { 0x, 0x1B7C, 0x, 0x0020 },
+   { 0x, 0x, 0x1B7C, 0x0020 }
+};
+
 struct hdmi_vmode {
bool mdataenablepolarity;
 
@@ -109,6 +115,7 @@ struct hdmi_data_info {
unsigned int pix_repet_factor;
unsigned int hdcp_enable;
struct hdmi_vmode video_mode;
+   bool rgb_limited_range;
 };
 
 struct dw_hdmi_i2c {
@@ -960,6 +967,13 @@ static int is_color_space_conversion(struct dw_hdmi *hdmi)
hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format);
 }
 
+static int is_rgb_downscale_needed(struct dw_hdmi *hdmi)
+{
+   return  hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) &&
+   hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) &&
+   hdmi->hdmi_data.rgb_limited_range;
+}
+
 static int is_color_space_decimation(struct dw_hdmi *hdmi)
 {
if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
@@ -1006,6 +1020,8 @@ static void dw_hdmi_update_csc_coeffs(struct dw_hdmi 
*hdmi)
csc_coeff = _coeff_rgb_in_eitu709;
csc_scale = 0;
}
+   } else if (is_rgb_downscale_needed(hdmi)) {
+   csc_coeff = _coeff_rgb_limited;
}
 
/* The CSC registers are sequential, alternating MSB then LSB */
@@ -1615,6 +1631,18 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct 
drm_display_mode *mode)
drm_hdmi_avi_infoframe_from_display_mode(,
 >connector, mode);
 
+   if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
+   drm_hdmi_avi_infoframe_quant_range(, >connector,
+  mode,
+  
hdmi->hdmi_data.rgb_limited_range ?
+  
HDMI_QUANTIZATION_RANGE_LIMITED :
+  
HDMI_QUANTIZATION_RANGE_FULL);
+   } else {
+   frame.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
+   frame.ycc_quantization_range =
+   HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
+   }
+
if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
frame.colorspace = HDMI_COLORSPACE_YUV444;
else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
@@ -1990,13 +2018,13 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi 
*hdmi)
hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
 
/* Enable csc path */
-   if (is_color_space_conversion(hdmi)) {
+   if (is_color_space_conversion(hdmi) || is_rgb_downscale_needed(hdmi)) {
hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
}
 
/* Enable color space conversion if needed */
-   if (is_color_space_conversion(hdmi))
+   if (is_color_space_conversion(hdmi) || is_rgb_downscale_needed(hdmi))
hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
HDMI_MC_FLOWCTRL);
else
@@ -2100,6 +2128,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct 
drm_display_mode *mode)
/* TOFIX: Default to RGB888 output format */
hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 
+   hdmi->hdmi_data.rgb_limited_range = hdmi->sink_is_hdmi &&
+   drm_default_rgb_quant_range(mode) ==
+   HDMI_QUANTIZATION_RANGE_LIMITED;
+
hdmi->hdmi_data.pix_repet_factor = 0;
hdmi->hdmi_data.hdcp_enable = 0;
hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 3/4] drm/bridge: dw-hdmi: do not force "none" scan mode

2020-03-02 Thread Jernej Skrabec
From: Jonas Karlman 

Setting scan mode to "none" confuses some TVs like LG B8, which randomly
change overscan procentage over time. Digital outputs like HDMI and DVI,
handled by this controller, don't really need overscan, so we can always
set scan mode to underscan. Actually, this is exactly what
drm_hdmi_avi_infoframe_from_display_mode() already does, so we can just
remove offending line.

Signed-off-by: Jonas Karlman 
[updated commit message]
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 9d7bfb1cb213..3d6021119942 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1655,8 +1655,6 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct 
drm_display_mode *mode)
HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
}
 
-   frame.scan_mode = HDMI_SCAN_MODE_NONE;
-
/*
 * The Designware IP uses a different byte format from standard
 * AVI info frames, though generally the bits are in the correct
-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 2/4] drm/bridge: dw-hdmi: Fix color space conversion detection

2020-03-02 Thread Jernej Skrabec
Currently, is_color_space_conversion() compares not only color spaces
but also formats. For example, function would return true if YCbCr 4:4:4
and YCbCr 4:2:2 would be set. Obviously in that case color spaces are
the same.

Fix that by comparing if both values represent RGB color space.

Fixes: b21f4b658df8 ("drm: imx: imx-hdmi: move imx-hdmi to bridge/dw_hdmi")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 24965e53d351..9d7bfb1cb213 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -956,7 +956,8 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
 
 static int is_color_space_conversion(struct dw_hdmi *hdmi)
 {
-   return hdmi->hdmi_data.enc_in_bus_format != 
hdmi->hdmi_data.enc_out_bus_format;
+   return hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) !=
+   hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format);
 }
 
 static int is_color_space_decimation(struct dw_hdmi *hdmi)
-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 1/4] drm/bridge: dw-hdmi: fix AVI frame colorimetry

2020-03-02 Thread Jernej Skrabec
CTA-861-F explicitly states that for RGB colorspace colorimetry should
be set to "none". Fix that.

Fixes: def23aa7e982 ("drm: bridge: dw-hdmi: Switch to V4L bus format and 
encodings")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 46 +--
 1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 67fca439bbfb..24965e53d351 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1624,28 +1624,34 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, 
struct drm_display_mode *mode)
frame.colorspace = HDMI_COLORSPACE_RGB;
 
/* Set up colorimetry */
-   switch (hdmi->hdmi_data.enc_out_encoding) {
-   case V4L2_YCBCR_ENC_601:
-   if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
-   frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
-   else
+   if (!hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
+   switch (hdmi->hdmi_data.enc_out_encoding) {
+   case V4L2_YCBCR_ENC_601:
+   if (hdmi->hdmi_data.enc_in_encoding == 
V4L2_YCBCR_ENC_XV601)
+   frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
+   else
+   frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
+   frame.extended_colorimetry =
+   HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+   break;
+   case V4L2_YCBCR_ENC_709:
+   if (hdmi->hdmi_data.enc_in_encoding == 
V4L2_YCBCR_ENC_XV709)
+   frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
+   else
+   frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
+   frame.extended_colorimetry =
+   HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
+   break;
+   default: /* Carries no data */
frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
+   frame.extended_colorimetry =
+   HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+   break;
+   }
+   } else {
+   frame.colorimetry = HDMI_COLORIMETRY_NONE;
frame.extended_colorimetry =
-   HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-   break;
-   case V4L2_YCBCR_ENC_709:
-   if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
-   frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
-   else
-   frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
-   frame.extended_colorimetry =
-   HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
-   break;
-   default: /* Carries no data */
-   frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
-   frame.extended_colorimetry =
-   HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-   break;
+   HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
}
 
frame.scan_mode = HDMI_SCAN_MODE_NONE;
-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 0/4] drm/bridge: dw-hdmi: Various updates

2020-03-02 Thread Jernej Skrabec
This series fixes multiple issues I found out.
Patch 1 fixes reporting colorimetry in AVI frame.
Patch 2 fixes color space conversion detection. At the moment it doesn't
change anything, but it would needlessly enable CSC unit when conversion
is not needed.
Patch 3 sets scan mode to underscan which is in line with most other hdmi
drivers.
Patch 4 aligns RGB quantization to CEA 861 standard.

Please take a look.

Best regards,
Jernej

Jernej Skrabec (3):
  drm/bridge: dw-hdmi: fix AVI frame colorimetry
  drm/bridge: dw-hdmi: Fix color space conversion detection
  drm/bridge: dw-hdmi: Add support for RGB limited range

Jonas Karlman (1):
  drm/bridge: dw-hdmi: do not force "none" scan mode

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 87 ---
 1 file changed, 62 insertions(+), 25 deletions(-)

-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 6/7] drm/sun4i: de2: Don't return de2_fmt_info struct

2020-02-25 Thread Jernej Skrabec
Now that de2_fmt_info contains only DRM <-> HW format mapping, it
doesn't make sense to return pointer to structure when searching by DRM
format. Rework that to return only HW format instead.

This doesn't make any functional change.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c| 15 +++
 drivers/gpu/drm/sun4i/sun8i_mixer.h|  7 +--
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 10 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 12 ++--
 4 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index e078ec96de2d..56cc037fd312 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -27,6 +27,11 @@
 #include "sun8i_vi_layer.h"
 #include "sunxi_engine.h"
 
+struct de2_fmt_info {
+   u32 drm_fmt;
+   u32 de2_fmt;
+};
+
 static const struct de2_fmt_info de2_formats[] = {
{
.drm_fmt = DRM_FORMAT_ARGB,
@@ -230,15 +235,17 @@ static const struct de2_fmt_info de2_formats[] = {
},
 };
 
-const struct de2_fmt_info *sun8i_mixer_format_info(u32 format)
+int sun8i_mixer_drm_format_to_hw(u32 format, u32 *hw_format)
 {
unsigned int i;
 
for (i = 0; i < ARRAY_SIZE(de2_formats); ++i)
-   if (de2_formats[i].drm_fmt == format)
-   return _formats[i];
+   if (de2_formats[i].drm_fmt == format) {
+   *hw_format = de2_formats[i].de2_fmt;
+   return 0;
+   }
 
-   return NULL;
+   return -EINVAL;
 }
 
 static void sun8i_mixer_commit(struct sunxi_engine *engine)
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h 
b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 0dd4a347fa06..7576b523fdbb 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -143,11 +143,6 @@
 #define SUN50I_MIXER_CDC0_EN   0xd
 #define SUN50I_MIXER_CDC1_EN   0xd8000
 
-struct de2_fmt_info {
-   u32 drm_fmt;
-   u32 de2_fmt;
-};
-
 /**
  * struct sun8i_mixer_cfg - mixer HW configuration
  * @vi_num: number of VI channels
@@ -207,5 +202,5 @@ sun8i_channel_base(struct sun8i_mixer *mixer, int channel)
return DE2_CH_BASE + channel * DE2_CH_SIZE;
 }
 
-const struct de2_fmt_info *sun8i_mixer_format_info(u32 format);
+int sun8i_mixer_drm_format_to_hw(u32 format, u32 *hw_format);
 #endif /* _SUN8I_MIXER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 99ee19a00415..a64aaea1ba74 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -174,20 +174,20 @@ static int sun8i_ui_layer_update_formats(struct 
sun8i_mixer *mixer, int channel,
 int overlay, struct drm_plane *plane)
 {
struct drm_plane_state *state = plane->state;
-   const struct de2_fmt_info *fmt_info;
const struct drm_format_info *fmt;
-   u32 val, ch_base;
+   u32 val, ch_base, hw_fmt;
+   int ret;
 
ch_base = sun8i_channel_base(mixer, channel);
 
fmt = state->fb->format;
-   fmt_info = sun8i_mixer_format_info(fmt->format);
-   if (!fmt_info || fmt->is_yuv) {
+   ret = sun8i_mixer_drm_format_to_hw(fmt->format, _fmt);
+   if (ret || fmt->is_yuv) {
DRM_DEBUG_DRIVER("Invalid format\n");
return -EINVAL;
}
 
-   val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET;
+   val = hw_fmt << SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET;
regmap_update_bits(mixer->engine.regs,
   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay),
   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index d783c2bfc77e..b1e1ba2da663 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -231,20 +231,20 @@ static int sun8i_vi_layer_update_formats(struct 
sun8i_mixer *mixer, int channel,
 int overlay, struct drm_plane *plane)
 {
struct drm_plane_state *state = plane->state;
-   const struct de2_fmt_info *fmt_info;
+   u32 val, ch_base, csc_mode, hw_fmt;
const struct drm_format_info *fmt;
-   u32 val, ch_base, csc_mode;
+   int ret;
 
ch_base = sun8i_channel_base(mixer, channel);
 
fmt = state->fb->format;
-   fmt_info = sun8i_mixer_format_info(fmt->format);
-   if (!fmt_info) {
+   ret = sun8i_mixer_drm_format_to_hw(fmt->format, _fmt);
+   if (ret) {
DRM_DEBUG_DRIVER("Invalid format\n");
-   return -EINVAL;
+  

[PATCH 7/7] drm/sun4i: Sort includes in VI and UI layer code

2020-02-25 Thread Jernej Skrabec
sun8i_mixer.h include is misplaced. Move it.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 2 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index a64aaea1ba74..54f937a7d5e7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -19,8 +19,8 @@
 #include 
 #include 
 
-#include "sun8i_ui_layer.h"
 #include "sun8i_mixer.h"
+#include "sun8i_ui_layer.h"
 #include "sun8i_ui_scaler.h"
 
 static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index b1e1ba2da663..22c8c5375d0d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -13,8 +13,8 @@
 #include 
 
 #include "sun8i_csc.h"
-#include "sun8i_vi_layer.h"
 #include "sun8i_mixer.h"
+#include "sun8i_vi_layer.h"
 #include "sun8i_vi_scaler.h"
 
 static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 5/7] drm/sun4i: de2: csc_mode in de2 format struct is mostly redundant

2020-02-25 Thread Jernej Skrabec
For RGB formats CSC mode is always set to none and for YUV formats
almost always set to YUV to RGB.

Add a helper function to deduce CSC mode from format.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c| 48 --
 drivers/gpu/drm/sun4i/sun8i_mixer.h|  6 ++--
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 24 +++--
 3 files changed, 23 insertions(+), 55 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 45e3cd9e718c..e078ec96de2d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -31,250 +31,202 @@ static const struct de2_fmt_info de2_formats[] = {
{
.drm_fmt = DRM_FORMAT_ARGB,
.de2_fmt = SUN8I_MIXER_FBFMT_ARGB,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_ABGR,
.de2_fmt = SUN8I_MIXER_FBFMT_ABGR,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_RGBA,
.de2_fmt = SUN8I_MIXER_FBFMT_RGBA,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_BGRA,
.de2_fmt = SUN8I_MIXER_FBFMT_BGRA,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_XRGB,
.de2_fmt = SUN8I_MIXER_FBFMT_XRGB,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_XBGR,
.de2_fmt = SUN8I_MIXER_FBFMT_XBGR,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_RGBX,
.de2_fmt = SUN8I_MIXER_FBFMT_RGBX,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_BGRX,
.de2_fmt = SUN8I_MIXER_FBFMT_BGRX,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_RGB888,
.de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_BGR888,
.de2_fmt = SUN8I_MIXER_FBFMT_BGR888,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_RGB565,
.de2_fmt = SUN8I_MIXER_FBFMT_RGB565,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_BGR565,
.de2_fmt = SUN8I_MIXER_FBFMT_BGR565,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_ARGB,
.de2_fmt = SUN8I_MIXER_FBFMT_ARGB,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
/* for DE2 VI layer which ignores alpha */
.drm_fmt = DRM_FORMAT_XRGB,
.de2_fmt = SUN8I_MIXER_FBFMT_ARGB,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_ABGR,
.de2_fmt = SUN8I_MIXER_FBFMT_ABGR,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
/* for DE2 VI layer which ignores alpha */
.drm_fmt = DRM_FORMAT_XBGR,
.de2_fmt = SUN8I_MIXER_FBFMT_ABGR,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_RGBA,
.de2_fmt = SUN8I_MIXER_FBFMT_RGBA,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
/* for DE2 VI layer which ignores alpha */
.drm_fmt = DRM_FORMAT_RGBX,
.de2_fmt = SUN8I_MIXER_FBFMT_RGBA,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_BGRA,
.de2_fmt = SUN8I_MIXER_FBFMT_BGRA,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
/* for DE2 VI layer which ignores alpha */
.drm_fmt = DRM_FORMAT_BGRX,
.de2_fmt = SUN8I_MIXER_FBFMT_BGRA,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_ARGB1555,
.de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
/* for DE2 VI layer which ignores alpha */
.drm_fmt = DRM_FORMAT_XRGB1555,
.de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_ABGR1555,
.de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555,
-   .csc = SUN8I_CSC_MODE_OFF,
},
{
/* for DE2 VI layer which ignores alpha */
.drm_fmt = DRM_FORMAT_XBGR1555,
.de2_fmt

[PATCH 1/7] drm/sun4i: de2/de3: Remove unsupported VI layer formats

2020-02-25 Thread Jernej Skrabec
YUV444 and YVU444 are planar formats, but HW format RGB888 is packed.
This means that those two mappings were never correct. Remove them.

Fixes: 60a3dcf96aa8 ("drm/sun4i: Add DE2 definitions for YUV formats")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c| 12 
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c |  2 --
 2 files changed, 14 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 7c24f8f832a5..3a78dbbceb8a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -196,12 +196,6 @@ static const struct de2_fmt_info de2_formats[] = {
.rgb = false,
.csc = SUN8I_CSC_MODE_YUV2RGB,
},
-   {
-   .drm_fmt = DRM_FORMAT_YUV444,
-   .de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
-   .rgb = true,
-   .csc = SUN8I_CSC_MODE_YUV2RGB,
-   },
{
.drm_fmt = DRM_FORMAT_YUV422,
.de2_fmt = SUN8I_MIXER_FBFMT_YUV422,
@@ -220,12 +214,6 @@ static const struct de2_fmt_info de2_formats[] = {
.rgb = false,
.csc = SUN8I_CSC_MODE_YUV2RGB,
},
-   {
-   .drm_fmt = DRM_FORMAT_YVU444,
-   .de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
-   .rgb = true,
-   .csc = SUN8I_CSC_MODE_YVU2RGB,
-   },
{
.drm_fmt = DRM_FORMAT_YVU422,
.de2_fmt = SUN8I_MIXER_FBFMT_YUV422,
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 42d445d23773..6a244d6fafd9 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -431,11 +431,9 @@ static const u32 sun8i_vi_layer_formats[] = {
DRM_FORMAT_YUV411,
DRM_FORMAT_YUV420,
DRM_FORMAT_YUV422,
-   DRM_FORMAT_YUV444,
DRM_FORMAT_YVU411,
DRM_FORMAT_YVU420,
DRM_FORMAT_YVU422,
-   DRM_FORMAT_YVU444,
 };
 
 struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 0/7] drm/sun4i: de2/de3 format fixes and updates

2020-02-25 Thread Jernej Skrabec
Currently VI layer code reported wrong formats for DE2 and DE3. First
three patches are fixes. Next two patches do code refactoring to remove
redundant information, which is already included elsewhere. Last two
patches are more cosmetic.

Note: It can be argued if patch 2 is really a fix. Consider that if only
patch 1 and 3 go into stable, wrong formats will be reported for DE3 VI
layers.

Please take a look.

Best regards,
Jernej

Jernej Skrabec (7):
  drm/sun4i: de2/de3: Remove unsupported VI layer formats
  drm/sun4i: Add separate DE3 VI layer formats
  drm/sun4i: Fix DE2 VI layer format support
  drm/sun4i: de2: rgb field in de2 format struct is redundant
  drm/sun4i: de2: csc_mode in de2 format struct is mostly redundant
  drm/sun4i: de2: Don't return de2_fmt_info struct
  drm/sun4i: Sort includes in VI and UI layer code

 drivers/gpu/drm/sun4i/sun8i_mixer.c| 159 -
 drivers/gpu/drm/sun4i/sun8i_mixer.h|  21 ++--
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c |  14 ++-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 106 ++---
 4 files changed, 183 insertions(+), 117 deletions(-)

-- 
2.25.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 3/7] drm/sun4i: Fix DE2 VI layer format support

2020-02-25 Thread Jernej Skrabec
DE2 VI layer doesn't support blending which means alpha channel is
ignored. Replace all formats with alpha with "don't care" (X) channel.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c| 56 ++
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 22 +-
 2 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 655445bfe64a..4a64f7ae437a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -106,48 +106,104 @@ static const struct de2_fmt_info de2_formats[] = {
.rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
+   {
+   /* for DE2 VI layer which ignores alpha */
+   .drm_fmt = DRM_FORMAT_XRGB,
+   .de2_fmt = SUN8I_MIXER_FBFMT_ARGB,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
{
.drm_fmt = DRM_FORMAT_ABGR,
.de2_fmt = SUN8I_MIXER_FBFMT_ABGR,
.rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
+   {
+   /* for DE2 VI layer which ignores alpha */
+   .drm_fmt = DRM_FORMAT_XBGR,
+   .de2_fmt = SUN8I_MIXER_FBFMT_ABGR,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
{
.drm_fmt = DRM_FORMAT_RGBA,
.de2_fmt = SUN8I_MIXER_FBFMT_RGBA,
.rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
+   {
+   /* for DE2 VI layer which ignores alpha */
+   .drm_fmt = DRM_FORMAT_RGBX,
+   .de2_fmt = SUN8I_MIXER_FBFMT_RGBA,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
{
.drm_fmt = DRM_FORMAT_BGRA,
.de2_fmt = SUN8I_MIXER_FBFMT_BGRA,
.rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
+   {
+   /* for DE2 VI layer which ignores alpha */
+   .drm_fmt = DRM_FORMAT_BGRX,
+   .de2_fmt = SUN8I_MIXER_FBFMT_BGRA,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
{
.drm_fmt = DRM_FORMAT_ARGB1555,
.de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
.rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
+   {
+   /* for DE2 VI layer which ignores alpha */
+   .drm_fmt = DRM_FORMAT_XRGB1555,
+   .de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
{
.drm_fmt = DRM_FORMAT_ABGR1555,
.de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555,
.rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
+   {
+   /* for DE2 VI layer which ignores alpha */
+   .drm_fmt = DRM_FORMAT_XBGR1555,
+   .de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
{
.drm_fmt = DRM_FORMAT_RGBA5551,
.de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551,
.rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
+   {
+   /* for DE2 VI layer which ignores alpha */
+   .drm_fmt = DRM_FORMAT_RGBX5551,
+   .de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
{
.drm_fmt = DRM_FORMAT_BGRA5551,
.de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551,
.rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
+   {
+   /* for DE2 VI layer which ignores alpha */
+   .drm_fmt = DRM_FORMAT_BGRX5551,
+   .de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
{
.drm_fmt = DRM_FORMAT_ARGB2101010,
.de2_fmt = SUN8I_MIXER_FBFMT_ARGB2101010,
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 6c0084a3c3d7..b8398ca18b0f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -398,26 +398,26 @@ static const struct drm_plane_funcs sun8i_vi_layer_funcs 
= {
 };
 
 /*
- * While all RGB formats are supported, VI planes don't support
- * alpha blending, so there is no point having formats with alpha
- * channel if their opaque analog exist.
+ * While DE2 VI layer supports same RGB formats as UI layer, alpha
+ * channel is ignored. This structure lists all unique variants
+ * where alpha channel is replaced with "don't care" (X) channel.
  */
 static const u32 su

[PATCH 4/7] drm/sun4i: de2: rgb field in de2 format struct is redundant

2020-02-25 Thread Jernej Skrabec
drm_format_info structure already contains information if format is RGB
or YUV. Use that instead.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c| 48 --
 drivers/gpu/drm/sun4i/sun8i_mixer.h|  1 -
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c |  6 ++--
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c |  6 ++--
 4 files changed, 8 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 4a64f7ae437a..45e3cd9e718c 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -31,297 +31,249 @@ static const struct de2_fmt_info de2_formats[] = {
{
.drm_fmt = DRM_FORMAT_ARGB,
.de2_fmt = SUN8I_MIXER_FBFMT_ARGB,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_ABGR,
.de2_fmt = SUN8I_MIXER_FBFMT_ABGR,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_RGBA,
.de2_fmt = SUN8I_MIXER_FBFMT_RGBA,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_BGRA,
.de2_fmt = SUN8I_MIXER_FBFMT_BGRA,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_XRGB,
.de2_fmt = SUN8I_MIXER_FBFMT_XRGB,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_XBGR,
.de2_fmt = SUN8I_MIXER_FBFMT_XBGR,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_RGBX,
.de2_fmt = SUN8I_MIXER_FBFMT_RGBX,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_BGRX,
.de2_fmt = SUN8I_MIXER_FBFMT_BGRX,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_RGB888,
.de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_BGR888,
.de2_fmt = SUN8I_MIXER_FBFMT_BGR888,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_RGB565,
.de2_fmt = SUN8I_MIXER_FBFMT_RGB565,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_BGR565,
.de2_fmt = SUN8I_MIXER_FBFMT_BGR565,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_ARGB,
.de2_fmt = SUN8I_MIXER_FBFMT_ARGB,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
/* for DE2 VI layer which ignores alpha */
.drm_fmt = DRM_FORMAT_XRGB,
.de2_fmt = SUN8I_MIXER_FBFMT_ARGB,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_ABGR,
.de2_fmt = SUN8I_MIXER_FBFMT_ABGR,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
/* for DE2 VI layer which ignores alpha */
.drm_fmt = DRM_FORMAT_XBGR,
.de2_fmt = SUN8I_MIXER_FBFMT_ABGR,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_RGBA,
.de2_fmt = SUN8I_MIXER_FBFMT_RGBA,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
/* for DE2 VI layer which ignores alpha */
.drm_fmt = DRM_FORMAT_RGBX,
.de2_fmt = SUN8I_MIXER_FBFMT_RGBA,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_BGRA,
.de2_fmt = SUN8I_MIXER_FBFMT_BGRA,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
/* for DE2 VI layer which ignores alpha */
.drm_fmt = DRM_FORMAT_BGRX,
.de2_fmt = SUN8I_MIXER_FBFMT_BGRA,
-   .rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
{
.drm_fmt = DRM_FORMAT_ARGB1555,
.de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
-   .rgb = true,
.csc

[PATCH 2/7] drm/sun4i: Add separate DE3 VI layer formats

2020-02-25 Thread Jernej Skrabec
DE3 VI layers support alpha blending, but DE2 VI layers do not.
Additionally, DE3 VI layers support 10-bit RGB and YUV formats.

Make a separate list for DE3.

Fixes: c50519e6db4d ("drm/sun4i: Add basic support for DE3")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c| 36 
 drivers/gpu/drm/sun4i/sun8i_mixer.h| 11 +
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 58 --
 3 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 3a78dbbceb8a..655445bfe64a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -148,6 +148,30 @@ static const struct de2_fmt_info de2_formats[] = {
.rgb = true,
.csc = SUN8I_CSC_MODE_OFF,
},
+   {
+   .drm_fmt = DRM_FORMAT_ARGB2101010,
+   .de2_fmt = SUN8I_MIXER_FBFMT_ARGB2101010,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
+   {
+   .drm_fmt = DRM_FORMAT_ABGR2101010,
+   .de2_fmt = SUN8I_MIXER_FBFMT_ABGR2101010,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
+   {
+   .drm_fmt = DRM_FORMAT_RGBA1010102,
+   .de2_fmt = SUN8I_MIXER_FBFMT_RGBA1010102,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
+   {
+   .drm_fmt = DRM_FORMAT_BGRA1010102,
+   .de2_fmt = SUN8I_MIXER_FBFMT_BGRA1010102,
+   .rgb = true,
+   .csc = SUN8I_CSC_MODE_OFF,
+   },
{
.drm_fmt = DRM_FORMAT_UYVY,
.de2_fmt = SUN8I_MIXER_FBFMT_UYVY,
@@ -232,6 +256,18 @@ static const struct de2_fmt_info de2_formats[] = {
.rgb = false,
.csc = SUN8I_CSC_MODE_YVU2RGB,
},
+   {
+   .drm_fmt = DRM_FORMAT_P010,
+   .de2_fmt = SUN8I_MIXER_FBFMT_P010_YUV,
+   .rgb = false,
+   .csc = SUN8I_CSC_MODE_YUV2RGB,
+   },
+   {
+   .drm_fmt = DRM_FORMAT_P210,
+   .de2_fmt = SUN8I_MIXER_FBFMT_P210_YUV,
+   .rgb = false,
+   .csc = SUN8I_CSC_MODE_YUV2RGB,
+   },
 };
 
 const struct de2_fmt_info *sun8i_mixer_format_info(u32 format)
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h 
b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index c6cc94057faf..345b28b0a80a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -93,6 +93,10 @@
 #define SUN8I_MIXER_FBFMT_ABGR1555 17
 #define SUN8I_MIXER_FBFMT_RGBA5551 18
 #define SUN8I_MIXER_FBFMT_BGRA5551 19
+#define SUN8I_MIXER_FBFMT_ARGB2101010  20
+#define SUN8I_MIXER_FBFMT_ABGR2101010  21
+#define SUN8I_MIXER_FBFMT_RGBA1010102  22
+#define SUN8I_MIXER_FBFMT_BGRA1010102  23
 
 #define SUN8I_MIXER_FBFMT_YUYV 0
 #define SUN8I_MIXER_FBFMT_UYVY 1
@@ -109,6 +113,13 @@
 /* format 12 is semi-planar YUV411 UVUV */
 /* format 13 is semi-planar YUV411 VUVU */
 #define SUN8I_MIXER_FBFMT_YUV411   14
+/* format 15 doesn't exist */
+/* format 16 is P010 YVU */
+#define SUN8I_MIXER_FBFMT_P010_YUV 17
+/* format 18 is P210 YVU */
+#define SUN8I_MIXER_FBFMT_P210_YUV 19
+/* format 20 is packed YVU444 10-bit */
+/* format 21 is packed YUV444 10-bit */
 
 /*
  * Sub-engines listed bellow are unused for now. The EN registers are here only
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 6a244d6fafd9..6c0084a3c3d7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -436,24 +436,76 @@ static const u32 sun8i_vi_layer_formats[] = {
DRM_FORMAT_YVU422,
 };
 
+static const u32 sun8i_vi_layer_de3_formats[] = {
+   DRM_FORMAT_ABGR1555,
+   DRM_FORMAT_ABGR2101010,
+   DRM_FORMAT_ABGR,
+   DRM_FORMAT_ABGR,
+   DRM_FORMAT_ARGB1555,
+   DRM_FORMAT_ARGB2101010,
+   DRM_FORMAT_ARGB,
+   DRM_FORMAT_ARGB,
+   DRM_FORMAT_BGR565,
+   DRM_FORMAT_BGR888,
+   DRM_FORMAT_BGRA1010102,
+   DRM_FORMAT_BGRA5551,
+   DRM_FORMAT_BGRA,
+   DRM_FORMAT_BGRA,
+   DRM_FORMAT_BGRX,
+   DRM_FORMAT_RGB565,
+   DRM_FORMAT_RGB888,
+   DRM_FORMAT_RGBA1010102,
+   DRM_FORMAT_RGBA,
+   DRM_FORMAT_RGBA5551,
+   DRM_FORMAT_RGBA,
+   DRM_FORMAT_RGBX,
+   DRM_FORMAT_XBGR,
+   DRM_FORMAT_XRGB,
+
+   DRM_FORMAT_NV16,
+   DRM_FORMAT_NV12,
+   DRM_FORMAT_NV21,
+   DRM_FORMAT_NV61,
+   DRM_FORMAT_P010,
+   DRM_FORMAT_P210,
+   DRM_FORMAT_UYVY,
+   DRM_FORMAT_VYUY,
+   DRM_FORMAT_YUYV,
+   DRM_FORMAT_YVYU,
+   DRM_FORMAT_YUV411,
+   DRM_FORMAT_YUV420,
+   DRM_FORMAT_YUV422,
+   DRM_FORMAT_YVU411,
+   DRM_FOR

[PATCH] Revert "drm/sun4i: drv: Allow framebuffer modifiers in mode config"

2020-01-27 Thread Jernej Skrabec
This reverts commit 9db9c0cf5895e4ddde2814360cae7bea9282edd2.

Setting mode_config.allow_fb_modifiers manually is completely
unnecessary. It is set automatically by drm_universal_plane_init() based
on the fact if modifier list is provided or not. Even more, it breaks
DE2 and DE3 as they don't support any modifiers beside linear. Modifiers
aware applications can be confused by provided empty modifier list - at
least linear modifier should be included, but it's not for DE2 and DE3.

Fixes: 9db9c0cf5895 ("drm/sun4i: drv: Allow framebuffer modifiers in mode 
config")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun4i_drv.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c 
b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 5ae67d526b1d..328272ff77d8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -85,7 +85,6 @@ static int sun4i_drv_bind(struct device *dev)
}
 
drm_mode_config_init(drm);
-   drm->mode_config.allow_fb_modifiers = true;
 
ret = component_bind_all(drm->dev, drm);
if (ret) {
-- 
2.25.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 3/3] drm/sun4i: sun8i-csc: Add support for color encoding and range

2019-07-13 Thread Jernej Skrabec
Conversion from YUV to RGB depends on range (limited or full) and
encoding (BT.601 or BT.709). Current code doesn't consider this and
always uses BT.601 encoding and limited range.

Fix this by introducing new CSC matrices, which are selected based on
range and encoding parameters.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_csc.c  | 144 -
 drivers/gpu/drm/sun4i/sun8i_csc.h  |   6 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c |   4 +-
 3 files changed, 126 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c 
b/drivers/gpu/drm/sun4i/sun8i_csc.c
index e07b7876d89b..70c792d052fe 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
@@ -18,16 +18,59 @@ static const u32 ccsc_base[2][2] = {
  * First tree values in each line are multiplication factor and last
  * value is constant, which is added at the end.
  */
-static const u32 yuv2rgb[] = {
-   0x04A8, 0x, 0x0662, 0xFFFC845A,
-   0x04A8, 0xFE6F, 0xFCBF, 0x00021DF4,
-   0x04A8, 0x0813, 0x, 0xFFFBAC4A,
+
+static const u32 yuv2rgb[2][2][12] = {
+   [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+   [DRM_COLOR_YCBCR_BT601] = {
+   0x04A8, 0x, 0x0662, 0xFFFC8451,
+   0x04A8, 0xFE6F, 0xFCC0, 0x00021E4D,
+   0x04A8, 0x0811, 0x, 0xFFFBACA9,
+   },
+   [DRM_COLOR_YCBCR_BT709] = {
+   0x04A8, 0x, 0x072B, 0xFFFC1F99,
+   0x04A8, 0xFF26, 0xFDDF, 0x00013383,
+   0x04A8, 0x0873, 0x, 0xFFFB7BEF,
+   }
+   },
+   [DRM_COLOR_YCBCR_FULL_RANGE] = {
+   [DRM_COLOR_YCBCR_BT601] = {
+   0x0400, 0x, 0x059B, 0xFFFD322E,
+   0x0400, 0xFEA0, 0xFD25, 0x00021DD5,
+   0x0400, 0x0716, 0x, 0xFFFC74BD,
+   },
+   [DRM_COLOR_YCBCR_BT709] = {
+   0x0400, 0x, 0x064C, 0xFFFCD9B4,
+   0x0400, 0xFF41, 0xFE21, 0x00014F96,
+   0x0400, 0x076C, 0x, 0xFFFC49EF,
+   }
+   },
 };
 
-static const u32 yvu2rgb[] = {
-   0x04A8, 0x0662, 0x, 0xFFFC845A,
-   0x04A8, 0xFCBF, 0xFE6F, 0x00021DF4,
-   0x04A8, 0x, 0x0813, 0xFFFBAC4A,
+static const u32 yvu2rgb[2][2][12] = {
+   [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+   [DRM_COLOR_YCBCR_BT601] = {
+   0x04A8, 0x0662, 0x, 0xFFFC8451,
+   0x04A8, 0xFCC0, 0xFE6F, 0x00021E4D,
+   0x04A8, 0x, 0x0811, 0xFFFBACA9,
+   },
+   [DRM_COLOR_YCBCR_BT709] = {
+   0x04A8, 0x072B, 0x, 0xFFFC1F99,
+   0x04A8, 0xFDDF, 0xFF26, 0x00013383,
+   0x04A8, 0x, 0x0873, 0xFFFB7BEF,
+   }
+   },
+   [DRM_COLOR_YCBCR_FULL_RANGE] = {
+   [DRM_COLOR_YCBCR_BT601] = {
+   0x0400, 0x059B, 0x, 0xFFFD322E,
+   0x0400, 0xFD25, 0xFEA0, 0x00021DD5,
+   0x0400, 0x, 0x0716, 0xFFFC74BD,
+   },
+   [DRM_COLOR_YCBCR_BT709] = {
+   0x0400, 0x064C, 0x, 0xFFFCD9B4,
+   0x0400, 0xFE21, 0xFF41, 0x00014F96,
+   0x0400, 0x, 0x076C, 0xFFFC49EF,
+   }
+   },
 };
 
 /*
@@ -53,30 +96,74 @@ static const u32 yvu2rgb[] = {
  * c20 c21 c22 [d2 const2]
  */
 
-static const u32 yuv2rgb_de3[] = {
-   0x0002542a, 0x, 0x0003312a, 0xffc0,
-   0x0002542a, 0x376b, 0xfffe5fc3, 0xfe00,
-   0x0002542a, 0x000408d3, 0x, 0xfe00,
+static const u32 yuv2rgb_de3[2][2][12] = {
+   [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+   [DRM_COLOR_YCBCR_BT601] = {
+   0x0002542A, 0x, 0x0003312A, 0xFFC0,
+   0x0002542A, 0x376B, 0xFFFE5FC3, 0xFE00,
+   0x0002542A, 0x000408D2, 0x, 0xFE00,
+   },
+   [DRM_COLOR_YCBCR_BT709] = {
+   0x0002542A, 0x, 0x000395E2, 0xFFC0,
+   0x0002542A, 0x92D2, 0xFFFEEF27, 0xFE00,
+   0x0002542A, 0x0004398C, 0x, 0xFE00,
+   }
+   },
+   [DRM_COLOR_YCBCR_FULL_RANGE] = {
+   [DRM_COLOR_YCBCR_BT601] = {
+   0x0002, 0x, 0x0002CDD2, 0x

[PATCH 2/3] drm/sun4i: sun8i_csc: Simplify register writes

2019-07-13 Thread Jernej Skrabec
It turns out addition of 0x200 to constant parts (+0.5) is not really
necessary. Besides, we can consider that before and fix value in CSC
matrix.

This simplifies register writes quiet a bit.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_csc.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c 
b/drivers/gpu/drm/sun4i/sun8i_csc.c
index b8c059f1a118..e07b7876d89b 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
@@ -69,7 +69,7 @@ static void sun8i_csc_set_coefficients(struct regmap *map, 
u32 base,
   enum sun8i_csc_mode mode)
 {
const u32 *table;
-   int i, data;
+   u32 base_reg;
 
switch (mode) {
case SUN8I_CSC_MODE_YUV2RGB:
@@ -83,13 +83,8 @@ static void sun8i_csc_set_coefficients(struct regmap *map, 
u32 base,
return;
}
 
-   for (i = 0; i < 12; i++) {
-   data = table[i];
-   /* For some reason, 0x200 must be added to constant parts */
-   if (((i + 1) & 3) == 0)
-   data += 0x200;
-   regmap_write(map, SUN8I_CSC_COEFF(base, i), data);
-   }
+   base_reg = SUN8I_CSC_COEFF(base, 0);
+   regmap_bulk_write(map, base_reg, table, 12);
 }
 
 static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer,
-- 
2.22.0



[PATCH 0/3] drm/sun4i: Add support for color encoding and range

2019-07-13 Thread Jernej Skrabec
In order to correctly convert image between YUV and RGB, you have to
know color encoding and color range. This patch set adds appropriate
properties and considers them when choosing CSC conversion matrix for
DE2 and DE3.

Note that this is only the half of needed changes when using HDMI output.
DW HDMI bridge driver has to be extended to have a property to select
limited (TVs) or full (PC monitors) range. But that will be done at a
later time.

Please take a look.

Best regards,
Jernej

Jernej Skrabec (3):
  drm/sun4i: Introduce color encoding and range properties
  drm/sun4i: sun8i_csc: Simplify register writes
  drm/sun4i: sun8i-csc: Add support for color encoding and range

 drivers/gpu/drm/sun4i/sun8i_csc.c  | 155 +++--
 drivers/gpu/drm/sun4i/sun8i_csc.h  |   6 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c |  21 +++-
 3 files changed, 146 insertions(+), 36 deletions(-)

-- 
2.22.0



[PATCH 1/3] drm/sun4i: Introduce color encoding and range properties

2019-07-13 Thread Jernej Skrabec
In order to correctly convert YUV color space to RGB, we have to know
color encoding and range.

Introduce these two properties using helper method.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index bd0e6a52d1d8..240a800217df 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -441,6 +441,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct 
drm_device *drm,
   struct sun8i_mixer *mixer,
   int index)
 {
+   u32 supported_encodings, supported_ranges;
struct sun8i_vi_layer *layer;
unsigned int plane_cnt;
int ret;
@@ -469,6 +470,22 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct 
drm_device *drm,
return ERR_PTR(ret);
}
 
+   supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
+ BIT(DRM_COLOR_YCBCR_BT709);
+
+   supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+  BIT(DRM_COLOR_YCBCR_FULL_RANGE);
+
+   ret = drm_plane_create_color_properties(>plane,
+   supported_encodings,
+   supported_ranges,
+   DRM_COLOR_YCBCR_BT709,
+   DRM_COLOR_YCBCR_LIMITED_RANGE);
+   if (ret) {
+   dev_err(drm->dev, "Couldn't add encoding and range 
properties!\n");
+   return ERR_PTR(ret);
+   }
+
drm_plane_helper_add(>plane, _vi_layer_helper_funcs);
layer->mixer = mixer;
layer->channel = index;
-- 
2.22.0



[PATCH 2/2] drm/sun4i: Fix sun8i HDMI PHY configuration for > 148.5 MHz

2019-05-14 Thread Jernej Skrabec
Vendor provided documentation says that EMP bits should be set to 3 for
pixel clocks greater than 148.5 MHz.

Fix that.

Cc: sta...@vger.kernel.org # 4.17+
Fixes: 4f86e81748fe ("drm/sun4i: Add support for H3 HDMI PHY variant")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index afc6d4a9c20b..43643ad31730 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -293,7 +293,8 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi,
 SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW |
 SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4);
ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(9) |
-SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(13);
+SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(13) |
+SUN8I_HDMI_PHY_ANA_CFG3_REG_EMP(3);
}
 
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
-- 
2.21.0



[PATCH 1/2] drm/sun4i: Fix sun8i HDMI PHY clock initialization

2019-05-14 Thread Jernej Skrabec
Current code initializes HDMI PHY clock driver before reset line is
deasserted and clocks enabled. Because of that, initial readout of
clock divider is incorrect (0 instead of 2). This causes any clock
rate with divider 1 (register value 0) to be set incorrectly.

Fix this by moving initialization of HDMI PHY clock driver after reset
line is deasserted and clocks enabled.

Cc: sta...@vger.kernel.org # 4.17+
Fixes: 4f86e81748fe ("drm/sun4i: Add support for H3 HDMI PHY variant")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 26 ++
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 66ea3a902e36..afc6d4a9c20b 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -672,22 +672,13 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, 
struct device_node *node)
goto err_put_clk_pll0;
}
}
-
-   ret = sun8i_phy_clk_create(phy, dev,
-  phy->variant->has_second_pll);
-   if (ret) {
-   dev_err(dev, "Couldn't create the PHY clock\n");
-   goto err_put_clk_pll1;
-   }
-
-   clk_prepare_enable(phy->clk_phy);
}
 
phy->rst_phy = of_reset_control_get_shared(node, "phy");
if (IS_ERR(phy->rst_phy)) {
dev_err(dev, "Could not get phy reset control\n");
ret = PTR_ERR(phy->rst_phy);
-   goto err_disable_clk_phy;
+   goto err_put_clk_pll1;
}
 
ret = reset_control_deassert(phy->rst_phy);
@@ -708,18 +699,29 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, 
struct device_node *node)
goto err_disable_clk_bus;
}
 
+   if (phy->variant->has_phy_clk) {
+   ret = sun8i_phy_clk_create(phy, dev,
+  phy->variant->has_second_pll);
+   if (ret) {
+   dev_err(dev, "Couldn't create the PHY clock\n");
+   goto err_disable_clk_mod;
+   }
+
+   clk_prepare_enable(phy->clk_phy);
+   }
+
hdmi->phy = phy;
 
return 0;
 
+err_disable_clk_mod:
+   clk_disable_unprepare(phy->clk_mod);
 err_disable_clk_bus:
clk_disable_unprepare(phy->clk_bus);
 err_deassert_rst_phy:
reset_control_assert(phy->rst_phy);
 err_put_rst_phy:
reset_control_put(phy->rst_phy);
-err_disable_clk_phy:
-   clk_disable_unprepare(phy->clk_phy);
 err_put_clk_pll1:
clk_put(phy->clk_pll1);
 err_put_clk_pll0:
-- 
2.21.0



[PATCH 0/2] drm/sun4i: Fix sun8i HDMI PHY initialization

2019-05-14 Thread Jernej Skrabec
I received a report that 4K resolution doesn't work if U-Boot video
driver is disabled. It turns out that HDMI PHY clock driver was
initialized prematurely, before reset line was deasserted and clocks
enabled. U-Boot video driver masked the issue because it set pixel
clock correctly.

In the process of researching the bug, I also found out that few bits
in HDMI PHY registers were not set correctly. While there is no
noticeable change (4K resolution works with both settings), I've
added fix anyway, to be conformant with vendor documentation.

Please check it out.

Best regards,
Jernej

Jernej Skrabec (2):
  drm/sun4i: Fix sun8i HDMI PHY clock initialization
  drm/sun4i: Fix sun8i HDMI PHY configuration for > 148.5 MHz

 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 29 ++
 1 file changed, 16 insertions(+), 13 deletions(-)

-- 
2.21.0



[PATCH v2 2/2] drm/sun4i: dw-hdmi: Bit bang CEC on some SoCs

2019-04-02 Thread Jernej Skrabec
All DW HDMI controllers used by Allwinner SoCs include CEC controller.
However, due to additional logic put between CEC controller and pins,
CEC communication doesn't work well on some of them.

Based on observations, it seems that only outgoing messages are
properly transmitted. It's possible that it would still work correctly
if pins are switched between input and output mode manually in right
moment. But that's very error prone. It's better and easier just to bit
bang protocol.

Enable bit banging just for controller and phy combination found in H3
and other 40nm SoCs. Other combinations work (H6) or the status is
unknown (A83T).

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/Kconfig  | 10 
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  | 11 
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 83 +-
 3 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 1dbbc3a1b763..7149c72e44c8 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -60,6 +60,16 @@ config DRM_SUN8I_DW_HDMI
  DesignWare HDMI controller with custom HDMI PHY. If M is
  selected the module will be called sun8i_dw_hdmi.
 
+config DRM_SUN8I_DW_HDMI_CEC
+   bool "Allwinner DesignWare HDMI CEC Support for 40nm SoCs"
+   depends on DRM_SUN8I_DW_HDMI
+   select CEC_CORE
+   select CEC_PIN
+   help
+ Choose this option if you have an 40nm Allwinner SoC with
+ the DesignWare HDMI controller with custom HDMI PHY and
+ you want to use CEC.
+
 config DRM_SUN8I_MIXER
tristate "Support for Allwinner Display Engine 2.0 Mixer"
default MACH_SUN8I
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 720c5aa8adc1..49ca001923e3 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define SUN8I_HDMI_PHY_DBG_CTRL_REG0x
 #define SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCKBIT(0)
@@ -144,6 +145,13 @@
 #define SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK   GENMASK(5, 0)
 
 #define SUN8I_HDMI_PHY_CEC_REG 0x003c
+#define SUN8I_HDMI_PHY_CEC_PIN_CTRLBIT(7)
+/*
+ * Documentation says that this bit is output enable. However,
+ * it seems that this bit is actually output disable.
+ */
+#define SUN8I_HDMI_PHY_CEC_OUT_DIS BIT(2)
+#define SUN8I_HDMI_PHY_CEC_IN_DATA BIT(1)
 
 struct sun8i_hdmi_phy;
 
@@ -151,6 +159,7 @@ struct sun8i_hdmi_phy_variant {
bool has_phy_clk;
bool has_second_pll;
unsigned int is_custom_phy : 1;
+   unsigned int bit_bang_cec : 1;
const struct dw_hdmi_curr_ctrl *cur_ctr;
const struct dw_hdmi_mpll_config *mpll_cfg;
const struct dw_hdmi_phy_config *phy_cfg;
@@ -163,6 +172,8 @@ struct sun8i_hdmi_phy_variant {
 };
 
 struct sun8i_hdmi_phy {
+   struct cec_adapter  *cec_adapter;
+   struct cec_notifier *cec_notifier;
struct clk  *clk_bus;
struct clk  *clk_mod;
struct clk  *clk_phy;
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 66ea3a902e36..8fd6bf91714e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -503,8 +503,9 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy 
*phy)
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
   SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK, 0);
 
-   /* set HW control of CEC pins */
-   regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG, 0);
+   /* manual control of CEC pins */
+   regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG,
+SUN8I_HDMI_PHY_CEC_PIN_CTRL);
 
/* read calibration data */
regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, );
@@ -530,8 +531,49 @@ void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
plat_data->cur_ctr = variant->cur_ctr;
plat_data->phy_config = variant->phy_cfg;
}
+   plat_data->disable_cec = phy->variant->bit_bang_cec;
 }
 
+#ifdef CONFIG_DRM_SUN8I_DW_HDMI_CEC
+static bool sun8i_hdmi_phy_cec_pin_read(struct cec_adapter *adap)
+{
+   struct sun8i_hdmi_phy *phy = cec_get_drvdata(adap);
+   unsigned int val;
+
+   regmap_read(phy->regs, SUN8I_HDMI_PHY_CEC_REG, );
+
+   return val & SUN8I_HDMI_PHY_CEC_IN_DATA;
+}
+
+static void sun8i_hdmi_phy_cec_pin_low(struct cec_adapter *adap)
+{
+   struct sun8i_hdmi_phy *phy = cec_get_drvdata(adap);
+
+   /* Start driving the CEC pin low */
+   regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG,
+SUN8I_HDMI_PHY_CEC_PIN_CTRL);
+}
+
+s

[PATCH v2 0/2] drm/sun4i: dw-hdmi: Improve CEC support

2019-04-02 Thread Jernej Skrabec
It turns out that additional logic between HDMI CEC controller and
pins on PHY on some Allwinner SoCs prevents proper communication.
It might be possible to fix it, but it's much easier and less error
prone to just directly drive pins using software implementation of
CEC protocol.

Let me know what do you think.

Best regards,
Jernej

Changes from v1:
- renamed is_cec_unusable to disable_cec
- added review-by tag

Jernej Skrabec (2):
  drm/bridge/synopsys: dw-hdmi: Add an option to suppress loading CEC
driver
  drm/sun4i: dw-hdmi: Bit bang CEC on some SoCs

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  2 +-
 drivers/gpu/drm/sun4i/Kconfig | 10 +++
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 11 +++
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c| 83 ++-
 include/drm/bridge/dw_hdmi.h  |  2 +
 5 files changed, 105 insertions(+), 3 deletions(-)

-- 
2.21.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v2 1/2] drm/bridge/synopsys: dw-hdmi: Add an option to suppress loading CEC driver

2019-04-02 Thread Jernej Skrabec
DW HDMI controller on some Allwinner SoCs has support for CEC, but due
to additional logic put between CEC controller and pins, it doesn't work
correctly, at least not with a lot of instrusive changes. Fortunately,
it's still possible to bitbang protocol.

For such cases, add a platform option to suppress loading CEC driver. If
DW HDMI CEC driver would be loaded, it wouldn't work anyway and would only
cause a confusion with multiple /dev entries.

Reviewed-by: Neil Armstrong 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +-
 include/drm/bridge/dw_hdmi.h  | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index db761329a1e3..d2b0aa8d964c 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2660,7 +2660,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->audio = platform_device_register_full();
}
 
-   if (config0 & HDMI_CONFIG0_CEC) {
+   if (!plat_data->disable_cec && (config0 & HDMI_CONFIG0_CEC)) {
cec.hdmi = hdmi;
cec.ops = _hdmi_cec_ops;
cec.irq = irq;
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 66e70770cce5..c03bea3a1a36 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -144,6 +144,8 @@ struct dw_hdmi_plat_data {
int (*configure_phy)(struct dw_hdmi *hdmi,
 const struct dw_hdmi_plat_data *pdata,
 unsigned long mpixelclock);
+
+   unsigned int disable_cec : 1;
 };
 
 struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
-- 
2.21.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 2/2] drm/sun4i: dw-hdmi: Bit bang CEC on some SoCs

2019-03-25 Thread Jernej Skrabec
All DW HDMI controllers used by Allwinner SoCs include CEC controller.
However, due to additional logic put between CEC controller and pins,
CEC communication doesn't work well on some of them.

Based on observations, it seems that only outgoing messages are
properly transmitted. It's possible that it would still work correctly
if pins are switched between input and output mode manually in right
moment. But that's very error prone. It's better and easier just to bit
bang protocol.

Enable bit banging just for controller and phy combination found in H3
and other 40nm SoCs. Other combinations work (H6) or the status is
unknown (A83T).

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/Kconfig  | 10 
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  | 11 
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 83 +-
 3 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 1dbbc3a1b763..7149c72e44c8 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -60,6 +60,16 @@ config DRM_SUN8I_DW_HDMI
  DesignWare HDMI controller with custom HDMI PHY. If M is
  selected the module will be called sun8i_dw_hdmi.
 
+config DRM_SUN8I_DW_HDMI_CEC
+   bool "Allwinner DesignWare HDMI CEC Support for 40nm SoCs"
+   depends on DRM_SUN8I_DW_HDMI
+   select CEC_CORE
+   select CEC_PIN
+   help
+ Choose this option if you have an 40nm Allwinner SoC with
+ the DesignWare HDMI controller with custom HDMI PHY and
+ you want to use CEC.
+
 config DRM_SUN8I_MIXER
tristate "Support for Allwinner Display Engine 2.0 Mixer"
default MACH_SUN8I
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 720c5aa8adc1..49ca001923e3 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define SUN8I_HDMI_PHY_DBG_CTRL_REG0x
 #define SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCKBIT(0)
@@ -144,6 +145,13 @@
 #define SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK   GENMASK(5, 0)
 
 #define SUN8I_HDMI_PHY_CEC_REG 0x003c
+#define SUN8I_HDMI_PHY_CEC_PIN_CTRLBIT(7)
+/*
+ * Documentation says that this bit is output enable. However,
+ * it seems that this bit is actually output disable.
+ */
+#define SUN8I_HDMI_PHY_CEC_OUT_DIS BIT(2)
+#define SUN8I_HDMI_PHY_CEC_IN_DATA BIT(1)
 
 struct sun8i_hdmi_phy;
 
@@ -151,6 +159,7 @@ struct sun8i_hdmi_phy_variant {
bool has_phy_clk;
bool has_second_pll;
unsigned int is_custom_phy : 1;
+   unsigned int bit_bang_cec : 1;
const struct dw_hdmi_curr_ctrl *cur_ctr;
const struct dw_hdmi_mpll_config *mpll_cfg;
const struct dw_hdmi_phy_config *phy_cfg;
@@ -163,6 +172,8 @@ struct sun8i_hdmi_phy_variant {
 };
 
 struct sun8i_hdmi_phy {
+   struct cec_adapter  *cec_adapter;
+   struct cec_notifier *cec_notifier;
struct clk  *clk_bus;
struct clk  *clk_mod;
struct clk  *clk_phy;
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 66ea3a902e36..70e291353569 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -503,8 +503,9 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy 
*phy)
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
   SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK, 0);
 
-   /* set HW control of CEC pins */
-   regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG, 0);
+   /* manual control of CEC pins */
+   regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG,
+SUN8I_HDMI_PHY_CEC_PIN_CTRL);
 
/* read calibration data */
regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, );
@@ -530,8 +531,49 @@ void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
plat_data->cur_ctr = variant->cur_ctr;
plat_data->phy_config = variant->phy_cfg;
}
+   plat_data->is_cec_unusable = phy->variant->bit_bang_cec;
 }
 
+#ifdef CONFIG_DRM_SUN8I_DW_HDMI_CEC
+static bool sun8i_hdmi_phy_cec_pin_read(struct cec_adapter *adap)
+{
+   struct sun8i_hdmi_phy *phy = cec_get_drvdata(adap);
+   unsigned int val;
+
+   regmap_read(phy->regs, SUN8I_HDMI_PHY_CEC_REG, );
+
+   return val & SUN8I_HDMI_PHY_CEC_IN_DATA;
+}
+
+static void sun8i_hdmi_phy_cec_pin_low(struct cec_adapter *adap)
+{
+   struct sun8i_hdmi_phy *phy = cec_get_drvdata(adap);
+
+   /* Start driving the CEC pin low */
+   regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG,
+SUN8I_HDMI_PHY_CEC_PIN_CTRL);
+}
+
+s

[PATCH 0/2] drm/sun4i: dw-hdmi: Improve CEC support

2019-03-25 Thread Jernej Skrabec
It turns out that additional logic between HDMI CEC controller and
pins on PHY on some Allwinner SoCs prevents proper communication.
It might be possible to fix it, but it's much easier and less error
prone to just directly drive pins using software implementation of
CEC protocol.

Let me know what do you think.

Best regards,
Jernej

Jernej Skrabec (2):
  drm/bridge/synopsys: dw-hdmi: Add an option to suppress loading CEC
driver
  drm/sun4i: dw-hdmi: Bit bang CEC on some SoCs

 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  2 +-
 drivers/gpu/drm/sun4i/Kconfig | 10 +++
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 11 +++
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c| 83 ++-
 include/drm/bridge/dw_hdmi.h  |  2 +
 5 files changed, 105 insertions(+), 3 deletions(-)

-- 
2.21.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH] drm/sun4i: DW HDMI: Lower max. supported rate for H6

2019-03-25 Thread Jernej Skrabec
Currently resolutions with pixel clock higher than 340 MHz don't work
with H6 HDMI controller. They just produce a blank screen.

Limit maximum pixel clock rate to 340 MHz until scrambling is supported.

Cc: sta...@vger.kernel.org # 5.0
Fixes: 40bb9d3147b2 ("drm/sun4i: Add support for H6 DW HDMI controller")
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index caea5a9f8f1d..ba4ce576b471 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -48,8 +48,13 @@ static enum drm_mode_status
 sun8i_dw_hdmi_mode_valid_h6(struct drm_connector *connector,
const struct drm_display_mode *mode)
 {
-   /* This is max for HDMI 2.0b (4K@60Hz) */
-   if (mode->clock > 594000)
+   /*
+* Controller support maximum of 594 MHz, which correlates to
+* 4K@60Hz 4:4:4 or RGB. However, for frequencies greater than
+* 340 MHz scrambling has to be enabled. Because scrambling is
+* not yet implemented, just limit to 340 MHz for now.
+*/
+   if (mode->clock > 34)
return MODE_CLOCK_HIGH;
 
return MODE_OK;
-- 
2.21.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 1/2] drm/bridge/synopsys: dw-hdmi: Add an option to suppress loading CEC driver

2019-03-25 Thread Jernej Skrabec
DW HDMI controller on some Allwinner SoCs has support for CEC, but due
to additional logic put between CEC controller and pins, it doesn't work
correctly, at least not with a lot of instrusive changes. Fortunately,
it's still possible to bitbang protocol.

For such cases, add a platform option to suppress loading CEC driver. If
DW HDMI CEC driver would be loaded, it wouldn't work anyway and only
cause a confusion with multiple /dev entries.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +-
 include/drm/bridge/dw_hdmi.h  | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index a63e5f0dae56..fdda26f8b056 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2634,7 +2634,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->audio = platform_device_register_full();
}
 
-   if (config0 & HDMI_CONFIG0_CEC) {
+   if (!plat_data->is_cec_unusable && (config0 & HDMI_CONFIG0_CEC)) {
cec.hdmi = hdmi;
cec.ops = _hdmi_cec_ops;
cec.irq = irq;
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 66e70770cce5..764b8bcfa62c 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -144,6 +144,8 @@ struct dw_hdmi_plat_data {
int (*configure_phy)(struct dw_hdmi *hdmi,
 const struct dw_hdmi_plat_data *pdata,
 unsigned long mpixelclock);
+
+   unsigned int is_cec_unusable : 1;
 };
 
 struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
-- 
2.21.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 0/3] drm/sun4i: DE2/DE3 improvements

2019-03-01 Thread Jernej Skrabec
DE2 and DE3 VI channels support coarse scaling to overcome VI scaler
limitations. That is especially useful for downscaling big planes, for
example 4K to 1080p.

Following patches were tested on H3 and A64 with 4K video playback on
1080p monitor. Without them, picture was mangled.

Please take a look.

Best regards,
Jernej

Jernej Skrabec (3):
  clk: sunxi-ng: Allow DE clock to set parent rate
  drm/sun4i: Add VI scaler line size quirk for DE2/DE3
  drm/sun4i: Improve VI scaling for DE2/DE3

 drivers/clk/sunxi-ng/ccu-sun50i-a64.c  |  3 +-
 drivers/clk/sunxi-ng/ccu-sun50i-h6.c   |  2 +-
 drivers/clk/sunxi-ng/ccu-sun8i-v3s.c   |  3 +-
 drivers/gpu/drm/sun4i/sun8i_mixer.c|  9 +
 drivers/gpu/drm/sun4i/sun8i_mixer.h|  2 +
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 54 --
 drivers/gpu/drm/sun4i/sun8i_vi_layer.h | 11 ++
 7 files changed, 78 insertions(+), 6 deletions(-)

-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 3/3] drm/sun4i: Improve VI scaling for DE2/DE3

2019-03-01 Thread Jernej Skrabec
VI planes support coarse scaling which helps to overcome VI scaler
limitations. While exact working of coarse scaling isn't known, it seems
that it just skips programmed amount of rows and columns. This is
especially useful for downscaling very big planes (4K down to 1080p).

Horizontal coarse scaling is currently used to fit one line to VI scaler
buffer.

Vertical coarse scaling is used to assure that VI scaler is actually
capable of processing framebuffer in one frame time.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 54 --
 drivers/gpu/drm/sun4i/sun8i_vi_layer.h | 11 ++
 2 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 8a0616238467..bb8e026d6405 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -80,6 +80,8 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer 
*mixer, int channel,
u32 bld_base, ch_base;
u32 outsize, insize;
u32 hphase, vphase;
+   u32 hn = 0, hm = 0;
+   u32 vn = 0, vm = 0;
bool subsampled;
 
DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
@@ -137,12 +139,41 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer 
*mixer, int channel,
subsampled = format->hsub > 1 || format->vsub > 1;
 
if (insize != outsize || subsampled || hphase || vphase) {
-   u32 hscale, vscale;
+   unsigned int scanline, required;
+   struct drm_display_mode *mode;
+   u32 hscale, vscale, fps;
+   u64 ability;
 
DRM_DEBUG_DRIVER("HW scaling is enabled\n");
 
-   hscale = state->src_w / state->crtc_w;
-   vscale = state->src_h / state->crtc_h;
+   mode = >state->crtc->state->mode;
+   fps = (mode->clock * 1000) / (mode->vtotal * mode->htotal);
+   ability = clk_get_rate(mixer->mod_clk);
+   /* BSP algorithm assumes 80% efficiency of VI scaler unit */
+   ability *= 80;
+   do_div(ability, mode->vdisplay * fps * max(src_w, dst_w));
+
+   required = src_h * 100 / dst_h;
+
+   if (ability < required) {
+   DRM_DEBUG_DRIVER("Using vertical coarse scaling\n");
+   vm = src_h;
+   vn = (u32)ability * dst_h / 100;
+   src_h = vn;
+   }
+
+   /* it seems that every RGB scaler has buffer for 2048 pixels */
+   scanline = subsampled ? mixer->cfg->scanline_yuv : 2048;
+
+   if (src_w > scanline) {
+   DRM_DEBUG_DRIVER("Using horizontal coarse scaling\n");
+   hm = src_w;
+   hn = scanline;
+   src_w = hn;
+   }
+
+   hscale = (src_w << 16) / dst_w;
+   vscale = (src_h << 16) / dst_h;
 
sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w,
  dst_h, hscale, vscale, hphase, vphase,
@@ -153,6 +184,23 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer 
*mixer, int channel,
sun8i_vi_scaler_enable(mixer, channel, false);
}
 
+   regmap_write(mixer->engine.regs,
+SUN8I_MIXER_CHAN_VI_HDS_Y(ch_base),
+SUN8I_MIXER_CHAN_VI_DS_N(hn) |
+SUN8I_MIXER_CHAN_VI_DS_M(hm));
+   regmap_write(mixer->engine.regs,
+SUN8I_MIXER_CHAN_VI_HDS_UV(ch_base),
+SUN8I_MIXER_CHAN_VI_DS_N(hn) |
+SUN8I_MIXER_CHAN_VI_DS_M(hm));
+   regmap_write(mixer->engine.regs,
+SUN8I_MIXER_CHAN_VI_VDS_Y(ch_base),
+SUN8I_MIXER_CHAN_VI_DS_N(vn) |
+SUN8I_MIXER_CHAN_VI_DS_M(vm));
+   regmap_write(mixer->engine.regs,
+SUN8I_MIXER_CHAN_VI_VDS_UV(ch_base),
+SUN8I_MIXER_CHAN_VI_DS_N(vn) |
+SUN8I_MIXER_CHAN_VI_DS_M(vm));
+
/* Set base coordinates */
DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
 state->dst.x1, state->dst.y1);
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h 
b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
index 8a5e6d01c85d..a223a4839f45 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
@@ -24,6 +24,14 @@
((base) + 0x30 * (layer) + 0x18 + 4 * (plane))
 #define SUN8I_MIXER_CHAN_VI_OVL_SIZE(base) \
((base) + 0xe8)
+#define SUN8I_MIXER_CHAN_VI_HDS_Y(base) \
+   ((base) + 0xf0)
+#define SUN8I_MIXER_CHAN_VI_HDS_UV(base) \
+   

[PATCH 2/3] drm/sun4i: Add VI scaler line size quirk for DE2/DE3

2019-03-01 Thread Jernej Skrabec
While all RGB scalers have maximum line size of 2048, some YUV scalers
have maximum line size of 2048 and some have line size of 4096.

Since there is no rule for that, add a quirk.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 9 +
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 2 ++
 2 files changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 30a2eff55687..a2c4807fc9b7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -554,6 +554,7 @@ static int sun8i_mixer_remove(struct platform_device *pdev)
 static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
.ccsc   = 0,
.scaler_mask= 0xf,
+   .scanline_yuv   = 2048,
.ui_num = 3,
.vi_num = 1,
 };
@@ -561,6 +562,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = 
{
 static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
.ccsc   = 1,
.scaler_mask= 0x3,
+   .scanline_yuv   = 2048,
.ui_num = 1,
.vi_num = 1,
 };
@@ -569,6 +571,7 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
.ccsc   = 0,
.mod_rate   = 43200,
.scaler_mask= 0xf,
+   .scanline_yuv   = 2048,
.ui_num = 3,
.vi_num = 1,
 };
@@ -577,6 +580,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
.ccsc   = 0,
.mod_rate   = 29700,
.scaler_mask= 0xf,
+   .scanline_yuv   = 2048,
.ui_num = 3,
.vi_num = 1,
 };
@@ -585,6 +589,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
.ccsc   = 1,
.mod_rate   = 29700,
.scaler_mask= 0x3,
+   .scanline_yuv   = 2048,
.ui_num = 1,
.vi_num = 1,
 };
@@ -593,6 +598,7 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
.vi_num = 2,
.ui_num = 1,
.scaler_mask = 0x3,
+   .scanline_yuv = 2048,
.ccsc = 0,
.mod_rate = 15000,
 };
@@ -601,6 +607,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = 
{
.ccsc   = 0,
.mod_rate   = 29700,
.scaler_mask= 0xf,
+   .scanline_yuv   = 4096,
.ui_num = 3,
.vi_num = 1,
 };
@@ -609,6 +616,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = 
{
.ccsc   = 1,
.mod_rate   = 29700,
.scaler_mask= 0x3,
+   .scanline_yuv   = 2048,
.ui_num = 1,
.vi_num = 1,
 };
@@ -618,6 +626,7 @@ static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
.is_de3 = true,
.mod_rate   = 6,
.scaler_mask= 0xf,
+   .scanline_yuv   = 4096,
.ui_num = 3,
.vi_num = 1,
 };
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h 
b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 913d14ce68b0..80e084caa084 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -159,6 +159,7 @@ struct de2_fmt_info {
  * @mod_rate: module clock rate that needs to be set in order to have
  * a functional block.
  * @is_de3: true, if this is next gen display engine 3.0, false otherwise.
+ * @scaline_yuv: size of a scanline for VI scaler for YUV formats.
  */
 struct sun8i_mixer_cfg {
int vi_num;
@@ -167,6 +168,7 @@ struct sun8i_mixer_cfg {
int ccsc;
unsigned long   mod_rate;
unsigned intis_de3 : 1;
+   unsigned intscanline_yuv;
 };
 
 struct sun8i_mixer {
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 1/3] clk: sunxi-ng: Allow DE clock to set parent rate

2019-03-01 Thread Jernej Skrabec
DE2/DE3 mixers have to run at specific frequency in order to work
optimally. This wasn't actually possible for some SoCs because "de"
clock wasn't allowed to adjust parent rate.

Add CLK_SET_RATE_PARENT flag to all "de" clocks which didn't have it
yet.

Signed-off-by: Jernej Skrabec 
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 3 ++-
 drivers/clk/sunxi-ng/ccu-sun50i-h6.c  | 2 +-
 drivers/clk/sunxi-ng/ccu-sun8i-v3s.c  | 3 ++-
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 932836d26e2b..be0deee70182 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -531,7 +531,8 @@ static SUNXI_CCU_GATE(dram_ts_clk,  "dram-ts",  "dram",
 
 static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
 static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
-0x104, 0, 4, 24, 3, BIT(31), 0);
+0x104, 0, 4, 24, 3, BIT(31),
+CLK_SET_RATE_PARENT);
 
 static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
 static const u8 tcon0_table[] = { 0, 2, };
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
index 139e8389615c..daf78966555e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
@@ -266,7 +266,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 
0x600,
   0, 4,/* M */
   24, 1,   /* mux */
   BIT(31), /* gate */
-  0);
+  CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
  0x60c, BIT(0), 0);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c 
b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
index ac12f261f8ca..eada0e291859 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
@@ -325,7 +325,8 @@ static SUNXI_CCU_GATE(dram_ohci_clk,"dram-ohci",
"dram",
 
 static const char * const de_parents[] = { "pll-video", "pll-periph0" };
 static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
-0x104, 0, 4, 24, 2, BIT(31), 0);
+0x104, 0, 4, 24, 2, BIT(31),
+CLK_SET_RATE_PARENT);
 
 static const char * const tcon_parents[] = { "pll-video" };
 static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents,
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v3 11/28] drm/sun4i: Disable unused DE2 sub-engines

2018-11-04 Thread Jernej Skrabec
Some sub-engines are unused. Disable them explicitly.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 8 
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 4 ++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 6769ec08c0d3..ec2c264f9481 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -462,6 +462,14 @@ static int sun8i_mixer_bind(struct device *dev, struct 
device *master,
/* Reset the registers */
for (i = 0; i < DE2_MIXER_UNIT_SIZE; i += 4)
regmap_write(mixer->engine.regs, i, 0);
+   /* Disable unused sub-engines */
+   regmap_write(mixer->engine.regs, SUN8I_MIXER_FCE_EN, 0);
+   regmap_write(mixer->engine.regs, SUN8I_MIXER_BWS_EN, 0);
+   regmap_write(mixer->engine.regs, SUN8I_MIXER_LTI_EN, 0);
+   regmap_write(mixer->engine.regs, SUN8I_MIXER_PEAK_EN, 0);
+   regmap_write(mixer->engine.regs, SUN8I_MIXER_ASE_EN, 0);
+   regmap_write(mixer->engine.regs, SUN8I_MIXER_FCC_EN, 0);
+   regmap_write(mixer->engine.regs, SUN8I_MIXER_DCSC_EN, 0);
 
/* Enable the mixer */
regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL,
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h 
b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 09e0f4428c1e..a4175b993e0d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -101,8 +101,8 @@
 #define SUN8I_MIXER_FBFMT_YUV411   14
 
 /*
- * These sub-engines are still unknown now, the EN registers are here only to
- * be used to disable these sub-engines.
+ * Sub-engines listed bellow are unused for now. The EN registers are here only
+ * to be used to disable these sub-engines.
  */
 #define SUN8I_MIXER_FCE_EN 0xa
 #define SUN8I_MIXER_BWS_EN 0xa2000
-- 
2.19.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 19/28] drm/sun4i: Add support for H6 DW HDMI controller

2018-11-04 Thread Jernej Skrabec
H6 has DW HDMI 2.0b controller v2.12a.

It supports 4K at 60 Hz and HDCP 2.2.

Reviewed-by: Chen-Yu Tsai 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 99b878e380e1..445cca8d9a26 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -44,6 +44,17 @@ sun8i_dw_hdmi_mode_valid_a83t(struct drm_connector 
*connector,
return MODE_OK;
 }
 
+static enum drm_mode_status
+sun8i_dw_hdmi_mode_valid_h6(struct drm_connector *connector,
+   const struct drm_display_mode *mode)
+{
+   /* This is max for HDMI 2.0b (4K@60Hz) */
+   if (mode->clock > 594000)
+   return MODE_CLOCK_HIGH;
+
+   return MODE_OK;
+}
+
 static bool sun8i_dw_hdmi_node_is_tcon_top(struct device_node *node)
 {
return IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
@@ -239,11 +250,19 @@ static const struct sun8i_dw_hdmi_quirks 
sun8i_a83t_quirks = {
.set_rate = true,
 };
 
+static const struct sun8i_dw_hdmi_quirks sun50i_h6_quirks = {
+   .mode_valid = sun8i_dw_hdmi_mode_valid_h6,
+};
+
 static const struct of_device_id sun8i_dw_hdmi_dt_ids[] = {
{
.compatible = "allwinner,sun8i-a83t-dw-hdmi",
.data = _a83t_quirks,
},
+   {
+   .compatible = "allwinner,sun50i-h6-dw-hdmi",
+   .data = _h6_quirks,
+   },
{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, sun8i_dw_hdmi_dt_ids);
-- 
2.19.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 16/28] drm/sun4i: dw-hdmi: Make mode_valid function configurable

2018-11-04 Thread Jernej Skrabec
Since it is not possible to access sun8i-dw-hdmi driver private data
inside mode_valid function, make it configurable. That way different
versions of HDMI controllers can set different function, depending on
it's limitations.

Reviewed-by: Chen-Yu Tsai 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 18 ++
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h |  6 ++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index ed2983770e9c..ec122136ee9d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -5,6 +5,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -33,8 +34,8 @@ static const struct drm_encoder_funcs 
sun8i_dw_hdmi_encoder_funcs = {
 };
 
 static enum drm_mode_status
-sun8i_dw_hdmi_mode_valid(struct drm_connector *connector,
-const struct drm_display_mode *mode)
+sun8i_dw_hdmi_mode_valid_a83t(struct drm_connector *connector,
+ const struct drm_display_mode *mode)
 {
if (mode->clock > 297000)
return MODE_CLOCK_HIGH;
@@ -102,6 +103,8 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
hdmi->dev = >dev;
encoder = >encoder;
 
+   hdmi->quirks = of_device_get_match_data(dev);
+
encoder->possible_crtcs =
sun8i_dw_hdmi_find_possible_crtcs(drm, dev->of_node);
/*
@@ -168,7 +171,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct 
device *master,
 
sun8i_hdmi_phy_init(hdmi->phy);
 
-   plat_data->mode_valid = _dw_hdmi_mode_valid;
+   plat_data->mode_valid = hdmi->quirks->mode_valid;
plat_data->phy_ops = sun8i_hdmi_phy_get_ops();
plat_data->phy_name = "sun8i_dw_hdmi_phy";
plat_data->phy_data = hdmi->phy;
@@ -230,8 +233,15 @@ static int sun8i_dw_hdmi_remove(struct platform_device 
*pdev)
return 0;
 }
 
+static const struct sun8i_dw_hdmi_quirks sun8i_a83t_quirks = {
+   .mode_valid = sun8i_dw_hdmi_mode_valid_a83t,
+};
+
 static const struct of_device_id sun8i_dw_hdmi_dt_ids[] = {
-   { .compatible = "allwinner,sun8i-a83t-dw-hdmi" },
+   {
+   .compatible = "allwinner,sun8i-a83t-dw-hdmi",
+   .data = _a83t_quirks,
+   },
{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, sun8i_dw_hdmi_dt_ids);
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 7fdc1ecd2892..a645b8bc9f58 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -170,6 +170,11 @@ struct sun8i_hdmi_phy {
struct sun8i_hdmi_phy_variant   *variant;
 };
 
+struct sun8i_dw_hdmi_quirks {
+   enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
+  const struct drm_display_mode *mode);
+};
+
 struct sun8i_dw_hdmi {
struct clk  *clk_tmds;
struct device   *dev;
@@ -178,6 +183,7 @@ struct sun8i_dw_hdmi {
struct sun8i_hdmi_phy   *phy;
struct dw_hdmi_plat_dataplat_data;
struct regulator*regulator;
+   const struct sun8i_dw_hdmi_quirks *quirks;
struct reset_control*rst_ctrl;
 };
 
-- 
2.19.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 20/28] drm/sun4i: dw-hdmi-phy: Reorder quirks by family

2018-11-04 Thread Jernej Skrabec
Currently, quirks and compatibles are sorted alphabetically. However,
they should be sorted by family release date and then alphabetically.

Fix that by moving A64 quirks and compatible to bottom. No functional
change is made.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 365cb5a9fb77..adc3ba7df7e3 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -403,13 +403,6 @@ static struct regmap_config sun8i_hdmi_phy_regmap_config = 
{
.name   = "phy"
 };
 
-static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = {
-   .has_phy_clk = true,
-   .phy_init = _hdmi_phy_init_h3,
-   .phy_disable = _hdmi_phy_disable_h3,
-   .phy_config = _hdmi_phy_config_h3,
-};
-
 static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = {
.phy_init = _hdmi_phy_init_a83t,
.phy_disable = _hdmi_phy_disable_a83t,
@@ -431,11 +424,14 @@ static const struct sun8i_hdmi_phy_variant 
sun8i_r40_hdmi_phy = {
.phy_config = _hdmi_phy_config_h3,
 };
 
+static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = {
+   .has_phy_clk = true,
+   .phy_init = _hdmi_phy_init_h3,
+   .phy_disable = _hdmi_phy_disable_h3,
+   .phy_config = _hdmi_phy_config_h3,
+};
+
 static const struct of_device_id sun8i_hdmi_phy_of_table[] = {
-   {
-   .compatible = "allwinner,sun50i-a64-hdmi-phy",
-   .data = _a64_hdmi_phy,
-   },
{
.compatible = "allwinner,sun8i-a83t-hdmi-phy",
.data = _a83t_hdmi_phy,
@@ -448,6 +444,10 @@ static const struct of_device_id sun8i_hdmi_phy_of_table[] 
= {
.compatible = "allwinner,sun8i-r40-hdmi-phy",
.data = _r40_hdmi_phy,
},
+   {
+   .compatible = "allwinner,sun50i-a64-hdmi-phy",
+   .data = _a64_hdmi_phy,
+   },
{ /* sentinel */ }
 };
 
-- 
2.19.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 27/28] arm64: dts: allwinner: h6: Add HDMI pipeline

2018-11-04 Thread Jernej Skrabec
This commit adds all entries needed for HDMI to function properly.

Signed-off-by: Jernej Skrabec 
[added DE3 bus]
Signed-off-by: Icenowy Zheng 
---
 arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 201 +++
 1 file changed, 201 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index 040828d2e2c0..59dda8f89d23 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -6,8 +6,11 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
+#include 
 
 / {
interrupt-parent = <>;
@@ -86,12 +89,63 @@
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};
 
+   de: display-engine {
+   compatible = "allwinner,sun50i-h6-display-engine";
+   allwinner,pipelines = <>;
+   status = "disabled";
+   };
+
soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;
 
+   de3@100 {
+   compatible = "allwinner,sun50i-h6-de3",
+"allwinner,sun50i-a64-de2";
+   reg = <0x100 0x40>;
+   allwinner,sram = <_sram 1>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0 0x100 0x40>;
+
+   display_clocks: clock@0 {
+   compatible = "allwinner,sun50i-h6-de3-clk";
+   reg = <0x0 0x1>;
+   clocks = < CLK_DE>,
+< CLK_BUS_DE>;
+   clock-names = "mod",
+ "bus";
+   resets = < RST_BUS_DE>;
+   #clock-cells = <1>;
+   #reset-cells = <1>;
+   };
+
+   mixer0: mixer@10 {
+   compatible = "allwinner,sun50i-h6-de3-mixer-0";
+   reg = <0x10 0x10>;
+   clocks = <_clocks CLK_BUS_MIXER0>,
+<_clocks CLK_MIXER0>;
+   clock-names = "bus",
+ "mod";
+   resets = <_clocks RST_MIXER0>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   mixer0_out: port@1 {
+   reg = <1>;
+
+   mixer0_out_tcon_top_mixer0: 
endpoint {
+   remote-endpoint = 
<_top_mixer0_in_mixer0>;
+   };
+   };
+   };
+   };
+   };
+
syscon: syscon@300 {
compatible = "allwinner,sun50i-h6-system-control",
 "allwinner,sun50i-a64-system-control";
@@ -149,6 +203,11 @@
interrupt-controller;
#interrupt-cells = <3>;
 
+   hdmi_pins: hdmi-pins {
+   pins = "PH8", "PH9", "PH10";
+   function = "hdmi";
+   };
+
mmc0_pins: mmc0-pins {
pins = "PF0", "PF1", "PF2", "PF3",
   "PF4", "PF5";
@@ -258,6 +317,148 @@
status = "disabled";
};
 
+   hdmi: hdmi@600 {
+   compatible = "allwinner,sun50i-h6-dw-hdmi";
+   reg = <0x0600 0x1>;
+   reg-io-width = <1>;
+   interrupts = ;
+   clocks = < CLK_BUS_HDMI>, < CLK_HDMI_SLOW>,
+< CLK_HDMI>, < CLK_HDMI_CEC>,
+< CLK_HDCP>, < CLK_BUS_HDCP>;
+   clock-names = "iahb", "isfr", "tmds", "cec", "hdcp&

[PATCH v3 26/28] drm: sun4i: add support for H6 TCON TOP

2018-11-04 Thread Jernej Skrabec
From: Icenowy Zheng 

The TCON TOP on Allwinner H6 SoC is a cut down version of the R40 TCON
TOP, which dropped TCON_TV1 and DSI (which do not exist on H6).

Add support for it.

Signed-off-by: Icenowy Zheng 
---
 drivers/gpu/drm/sun4i/sun8i_tcon_top.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c 
b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
index e94e3fb1736b..fc36e0c10a37 100644
--- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
+++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
@@ -273,12 +273,20 @@ const struct sun8i_tcon_top_quirks 
sun8i_r40_tcon_top_quirks = {
.has_dsi= true,
 };
 
+const struct sun8i_tcon_top_quirks sun50i_h6_tcon_top_quirks = {
+   /* Nothing special */
+};
+
 /* sun4i_drv uses this list to check if a device node is a TCON TOP */
 const struct of_device_id sun8i_tcon_top_of_table[] = {
{
.compatible = "allwinner,sun8i-r40-tcon-top",
.data = _r40_tcon_top_quirks
},
+   {
+   .compatible = "allwinner,sun50i-h6-tcon-top",
+   .data = _h6_tcon_top_quirks
+   },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sun8i_tcon_top_of_table);
-- 
2.19.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 17/28] drm/sun4i: dw-hdmi: Add quirk for setting TMDS clock

2018-11-04 Thread Jernej Skrabec
It turns out that H6 HDMI BSP kernel driver doesn't change TMDS rate at
all. At this point it is not clear whether it is just not necessary or
it would cause some kind of issues.

Add a quirk for it.

Acked-by: Maxime Ripard 
Reviewed-by: Chen-Yu Tsai 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 4 +++-
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index ec122136ee9d..99b878e380e1 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -21,7 +21,8 @@ static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder 
*encoder,
 {
struct sun8i_dw_hdmi *hdmi = encoder_to_sun8i_dw_hdmi(encoder);
 
-   clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000);
+   if (hdmi->quirks->set_rate)
+   clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000);
 }
 
 static const struct drm_encoder_helper_funcs
@@ -235,6 +236,7 @@ static int sun8i_dw_hdmi_remove(struct platform_device 
*pdev)
 
 static const struct sun8i_dw_hdmi_quirks sun8i_a83t_quirks = {
.mode_valid = sun8i_dw_hdmi_mode_valid_a83t,
+   .set_rate = true,
 };
 
 static const struct of_device_id sun8i_dw_hdmi_dt_ids[] = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index a645b8bc9f58..49c9e80c46ea 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -173,6 +173,7 @@ struct sun8i_hdmi_phy {
 struct sun8i_dw_hdmi_quirks {
enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
   const struct drm_display_mode *mode);
+   unsigned int set_rate : 1;
 };
 
 struct sun8i_dw_hdmi {
-- 
2.19.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 08/28] drm/sun4i: Add compatible for H6 display engine

2018-11-04 Thread Jernej Skrabec
H6 is first Allwinner SoC which supports 10 bit colors, HDR and AFBC.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun4i_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c 
b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 1e41c3f5fd6d..1ca7b70cbbfa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -406,6 +406,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
{ .compatible = "allwinner,sun8i-v3s-display-engine" },
{ .compatible = "allwinner,sun9i-a80-display-engine" },
{ .compatible = "allwinner,sun50i-a64-display-engine" },
+   { .compatible = "allwinner,sun50i-h6-display-engine" },
{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
-- 
2.19.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 06/28] clk: sunxi-ng: Add support for H6 DE3 clocks

2018-11-04 Thread Jernej Skrabec
Support for mixer0, mixer1, writeback and rotation units is added.

Signed-off-by: Jernej Skrabec 
Signed-off-by: Icenowy Zheng 
---
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 71 ++--
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h |  4 +-
 2 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c 
b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
index bae5ee67a797..1c9ae0a319c1 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -31,6 +31,8 @@ static SUNXI_CCU_GATE(bus_mixer1_clk, "bus-mixer1",   
"bus-de",
  0x04, BIT(1), 0);
 static SUNXI_CCU_GATE(bus_wb_clk,  "bus-wb",   "bus-de",
  0x04, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_rot_clk, "bus-rot",  "bus-de",
+ 0x04, BIT(3), 0);
 
 static SUNXI_CCU_GATE(mixer0_clk,  "mixer0",   "mixer0-div",
  0x00, BIT(0), CLK_SET_RATE_PARENT);
@@ -38,6 +40,8 @@ static SUNXI_CCU_GATE(mixer1_clk, "mixer1",   
"mixer1-div",
  0x00, BIT(1), CLK_SET_RATE_PARENT);
 static SUNXI_CCU_GATE(wb_clk,  "wb",   "wb-div",
  0x00, BIT(2), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(rot_clk, "rot",  "rot-div",
+ 0x00, BIT(3), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4,
   CLK_SET_RATE_PARENT);
@@ -45,6 +49,8 @@ static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 
4, 4,
   CLK_SET_RATE_PARENT);
 static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4,
   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(rot_div_clk, "rot-div", "de", 0x0c, 0x0c, 4,
+  CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_M(mixer0_div_a83_clk, "mixer0-div", "pll-de", 0x0c, 0, 4,
   CLK_SET_RATE_PARENT);
@@ -53,6 +59,24 @@ static SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", 
"pll-de", 0x0c, 4, 4,
 static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4,
   CLK_SET_RATE_PARENT);
 
+static struct ccu_common *sun50i_h6_de3_clks[] = {
+   _clk.common,
+   _clk.common,
+   _clk.common,
+
+   _mixer0_clk.common,
+   _mixer1_clk.common,
+   _wb_clk.common,
+
+   _div_clk.common,
+   _div_clk.common,
+   _div_clk.common,
+
+   _rot_clk.common,
+   _clk.common,
+   _div_clk.common,
+};
+
 static struct ccu_common *sun8i_a83t_de2_clks[] = {
_clk.common,
_clk.common,
@@ -106,7 +130,7 @@ static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = {
[CLK_MIXER1_DIV]= _div_a83_clk.common.hw,
[CLK_WB_DIV]= _div_a83_clk.common.hw,
},
-   .num= CLK_NUMBER,
+   .num= CLK_NUMBER_WITHOUT_ROT,
 };
 
 static struct clk_hw_onecell_data sun8i_h3_de2_hw_clks = {
@@ -123,7 +147,7 @@ static struct clk_hw_onecell_data sun8i_h3_de2_hw_clks = {
[CLK_MIXER1_DIV]= _div_clk.common.hw,
[CLK_WB_DIV]= _div_clk.common.hw,
},
-   .num= CLK_NUMBER,
+   .num= CLK_NUMBER_WITHOUT_ROT,
 };
 
 static struct clk_hw_onecell_data sun8i_v3s_de2_hw_clks = {
@@ -137,7 +161,27 @@ static struct clk_hw_onecell_data sun8i_v3s_de2_hw_clks = {
[CLK_MIXER0_DIV]= _div_clk.common.hw,
[CLK_WB_DIV]= _div_clk.common.hw,
},
-   .num= CLK_NUMBER,
+   .num= CLK_NUMBER_WITHOUT_ROT,
+};
+
+static struct clk_hw_onecell_data sun50i_h6_de3_hw_clks = {
+   .hws= {
+   [CLK_MIXER0]= _clk.common.hw,
+   [CLK_MIXER1]= _clk.common.hw,
+   [CLK_WB]= _clk.common.hw,
+   [CLK_ROT]   = _clk.common.hw,
+
+   [CLK_BUS_MIXER0]= _mixer0_clk.common.hw,
+   [CLK_BUS_MIXER1]= _mixer1_clk.common.hw,
+   [CLK_BUS_WB]= _wb_clk.common.hw,
+   [CLK_BUS_ROT]   = _rot_clk.common.hw,
+
+   [CLK_MIXER0_DIV]= _div_clk.common.hw,
+   [CLK_MIXER1_DIV]= _div_clk.common.hw,
+   [CLK_WB_DIV]= _div_clk.common.hw,
+   [CLK_ROT_DIV]   = _div_clk.common.hw,
+   },
+   .num= CLK_NUMBER_WITH_ROT,
 };
 
 static struct ccu_reset_map sun8i_a83t_de2_resets[] = {
@@ -156,6 +200,13 @@ static struct ccu_reset_map sun50i_a64_de2_resets[] = {
[RST_WB]= { 0x08, BIT(2) },
 };
 
+static struct ccu_reset_map sun50i_h6_

[PATCH v3 12/28] drm/sun4i: Add basic support for DE3

2018-11-04 Thread Jernej Skrabec
Display Engine 3 is an upgrade of DE2 with new features like support for
10 bit color formats and support for AFBC.

Most of DE2 code works with DE3, except some small details.

Implement basic support for DE3. Support for 10 bit colort formats and
AFBC, among others missing features, will be added later.

Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_csc.c   | 83 +
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 38 +++
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 34 +-
 drivers/gpu/drm/sun4i/sun8i_ui_scaler.c | 10 ++-
 drivers/gpu/drm/sun4i/sun8i_ui_scaler.h |  1 +
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c  |  8 +++
 drivers/gpu/drm/sun4i/sun8i_vi_layer.h  |  2 +
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 19 +-
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.h | 23 +++
 9 files changed, 202 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c 
b/drivers/gpu/drm/sun4i/sun8i_csc.c
index b14925b40ccf..e7608a72f26f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
@@ -34,6 +34,41 @@ static const u32 yvu2rgb[] = {
0x04A8, 0x, 0x0813, 0xFFFBAC4A,
 };
 
+/*
+ * DE3 has a bit different CSC units. Factors are in two's complement format.
+ * First three factors in a row are multiplication factors which have 17 bits
+ * for fractional part. Fourth value in a row is comprised of two factors.
+ * Upper 16 bits represents difference, which is subtracted from the input
+ * value before multiplication and lower 16 bits represents constant, which
+ * is addes at the end.
+ *
+ * x' = c00 * (x + d0) + c01 * (y + d1) + c02 * (z + d2) + const0
+ * y' = c10 * (x + d0) + c11 * (y + d1) + c12 * (z + d2) + const1
+ * z' = c20 * (x + d0) + c21 * (y + d1) + c22 * (z + d2) + const2
+ *
+ * Please note that above formula is true only for Blender CSC. Other DE3 CSC
+ * units takes only positive value for difference. From what can be deducted
+ * from BSP driver code, those units probably automatically assume that
+ * difference has to be subtracted.
+ *
+ * Layout of factors in table:
+ * c00 c01 c02 [d0 const0]
+ * c10 c11 c12 [d1 const1]
+ * c20 c21 c22 [d2 const2]
+ */
+
+static const u32 yuv2rgb_de3[] = {
+   0x0002542a, 0x, 0x0003312a, 0xffc0,
+   0x0002542a, 0x376b, 0xfffe5fc3, 0xfe00,
+   0x0002542a, 0x000408d3, 0x, 0xfe00,
+};
+
+static const u32 yvu2rgb_de3[] = {
+   0x0002542a, 0x0003312a, 0x, 0xffc0,
+   0x0002542a, 0xfffe5fc3, 0x376b, 0xfe00,
+   0x0002542a, 0x, 0x000408d3, 0xfe00,
+};
+
 static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
   enum sun8i_csc_mode mode)
 {
@@ -61,6 +96,28 @@ static void sun8i_csc_set_coefficients(struct regmap *map, 
u32 base,
}
 }
 
+static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer,
+   enum sun8i_csc_mode mode)
+{
+   const u32 *table;
+   u32 base_reg;
+
+   switch (mode) {
+   case SUN8I_CSC_MODE_YUV2RGB:
+   table = yuv2rgb_de3;
+   break;
+   case SUN8I_CSC_MODE_YVU2RGB:
+   table = yvu2rgb_de3;
+   break;
+   default:
+   DRM_WARN("Wrong CSC mode specified.\n");
+   return;
+   }
+
+   base_reg = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0, 0);
+   regmap_bulk_write(map, base_reg, table, 12);
+}
+
 static void sun8i_csc_enable(struct regmap *map, u32 base, bool enable)
 {
u32 val;
@@ -73,11 +130,32 @@ static void sun8i_csc_enable(struct regmap *map, u32 base, 
bool enable)
regmap_update_bits(map, SUN8I_CSC_CTRL(base), SUN8I_CSC_CTRL_EN, val);
 }
 
+static void sun8i_de3_ccsc_enable(struct regmap *map, int layer, bool enable)
+{
+   u32 val, mask;
+
+   mask = SUN50I_MIXER_BLEND_CSC_CTL_EN(layer);
+
+   if (enable)
+   val = mask;
+   else
+   val = 0;
+
+   regmap_update_bits(map, SUN50I_MIXER_BLEND_CSC_CTL(DE3_BLD_BASE),
+  mask, val);
+}
+
 void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
 enum sun8i_csc_mode mode)
 {
u32 base;
 
+   if (mixer->cfg->is_de3) {
+   sun8i_de3_ccsc_set_coefficients(mixer->engine.regs,
+   layer, mode);
+   return;
+   }
+
base = ccsc_base[mixer->cfg->ccsc][layer];
 
sun8i_csc_set_coefficients(mixer->engine.regs, base, mode);
@@ -87,6 +165,11 @@ void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int 
layer, bool enable)
 {
u32 base;
 
+   if (mixer->cfg->is_de3) {
+   sun8i_de3_ccsc_enable(mixer->engine.regs, layer, enable);
+   return;
+   }
+
bas

[PATCH v3 00/28] Allwinner H6 DE3 and HDMI support

2018-11-04 Thread Jernej Skrabec
This series adds support for Display Engine 3.0 and HDMI 2.0a, which
can be found on H6 SoC.

Display Engine 3.0 in comparison to 2.0 mostly adds features needed for
displaying and processing 10-bit and AFBC formats, which are not yet
supported by this series.

H6 is also the first SoC which supports IOMMU, but support for it is
not yet added.

This series is based on linux-next at next-20181102.

I suggest all patches go through allwinner tree, except DRM patches,
which should go through drm-misc tree.

Last detail, PineH64 model A schematic has DDC_EN signal, which enables
DDC voltage level shifter. TL Lim, PINE64 founder, said that this
signal is not actually present on PineH64 model A board. It is, however
present on PineH64 model B engineering samples, but it will be removed
in production version. Because of that, I didn't include any code for
it.

Please take a look.

Best regards,
Jernej

Changes from v2:
- Collected tags
- Removed patch which renames all DE2 macros
- Converted bool struct members in header files to unsigned int bitfield.
  This issue was reported by checkpatch.pl --strict.
- Fixed code style in tcon top driver and removed unnecessary initialization
- Moved set_rate quirk check in dw-hdmi driver to more appropriate place
- Fixed compatible for H6 DE3 bus compatible

Changes from v1:
- Collected tags
- Reworked some commit messages and titles
- Remove two patches which were already merged
- Added new patches (10, 11, 12, 21)
- Lowered max. supported HDMI pixel clock to 594 MHz
- Reordered compatibles and quirks by family name
- Fixed kbuild test robot warnings
- renamed CLK_NUMBER to CLK_NUMBER_WITHOUT_ROT and introduced
  CLK_NUMBER_WITH_ROT
- removed "inline" from functions in c file
- used regmap_bulk_write() for writing DE3 CSC table
- DE3 specific macros have "DE3_" prefix now
- reworked DE2/3 mixer registers initialization
- removed writing to edge detection registers because
  functionality is not used

Icenowy Zheng (5):
  dt-bindings: bus: add H6 DE3 bus binding
  dt-bindings: display: sunxi: add DT binding for Allwinner H6 DW HDMI
  drm: sun4i: add quirks for TCON TOP
  dt-bindings: display: sun4i-drm: document H6 TCON TOP
  drm: sun4i: add support for H6 TCON TOP

Jernej Skrabec (23):
  clk: sunxi-ng: Adjust MP clock parent rate when allowed
  clk: sunxi-ng: Use u64 for calculation of NM rate
  clk: sunxi-ng: h6: Set video PLLs limits
  dt-bindings: clock: sun8i-de2: Add H6 DE3 clock description
  clk: sunxi-ng: Add support for H6 DE3 clocks
  dt-bindings: display: sun4i-drm: Add H6 display engine compatibles
  drm/sun4i: Add compatible for H6 display engine
  drm/sun4i: Rework DE2 register defines
  drm/sun4i: Fix DE2 mixer size
  drm/sun4i: Disable unused DE2 sub-engines
  drm/sun4i: Add basic support for DE3
  drm/sun4i: Add support for H6 DE3 mixer 0
  drm/bridge/synopsys: dw-hdmi: Enable workaround for v2.12a
  drm/sun4i: Not all DW HDMI controllers has scrambled addresses
  drm/sun4i: dw-hdmi: Make mode_valid function configurable
  drm/sun4i: dw-hdmi: Add quirk for setting TMDS clock
  drm/sun4i: Add support for H6 DW HDMI controller
  drm/sun4i: dw-hdmi-phy: Reorder quirks by family
  drm/sun4i: Add support for Synopsys HDMI PHY
  drm/sun4i: Add support for H6 HDMI PHY
  drm/sun4i: Initialize registers in tcon-top driver
  arm64: dts: allwinner: h6: Add HDMI pipeline
  arm64: dts: allwinner: h6: Enable HDMI output on Pine H64 board

 .../bindings/bus/sun50i-de2-bus.txt   |   9 +-
 .../devicetree/bindings/clock/sun8i-de2.txt   |   5 +-
 .../bindings/display/sunxi/sun4i-drm.txt  |  30 ++-
 .../boot/dts/allwinner/sun50i-h6-pine-h64.dts |  25 +++
 arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi  | 201 ++
 drivers/clk/sunxi-ng/ccu-sun50i-h6.c  |   4 +
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c  |  71 ++-
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h  |   4 +-
 drivers/clk/sunxi-ng/ccu_mp.c |  64 +-
 drivers/clk/sunxi-ng/ccu_nm.c |  18 +-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |   1 +
 drivers/gpu/drm/sun4i/sun4i_drv.c |   1 +
 drivers/gpu/drm/sun4i/sun8i_csc.c |  83 
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c |  45 +++-
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h |  14 +-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c| 201 --
 drivers/gpu/drm/sun4i/sun8i_mixer.c   |  57 -
 drivers/gpu/drm/sun4i/sun8i_mixer.h   |  80 +--
 drivers/gpu/drm/sun4i/sun8i_tcon_top.c|  52 -
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c|  47 ++--
 drivers/gpu/drm/sun4i/sun8i_ui_layer.h|  37 ++--
 drivers/gpu/drm/sun4i/sun8i_ui_scaler.c   |  47 ++--
 drivers/gpu/drm/sun4i/sun8i_ui_scaler.h   |  28 +--
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c|  55 +++--
 drivers/gpu/drm/sun4i/sun8i_vi_layer.h|  25 ++-
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c   |  70 --
 d

[PATCH v3 01/28] dt-bindings: bus: add H6 DE3 bus binding

2018-11-04 Thread Jernej Skrabec
From: Icenowy Zheng 

The Allwinner H6 DE3 bus is similar to the A64 DE2 one.

Add its compatible string with the A64 string as fallback to the
binding.

Some description of the binding is modified to make it more generic.

Reviewed-by: Rob Herring 
Signed-off-by: Icenowy Zheng 
[Fixed compatible name]
Signed-off-by: Jernej Skrabec 
---
 Documentation/devicetree/bindings/bus/sun50i-de2-bus.txt | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/bus/sun50i-de2-bus.txt 
b/Documentation/devicetree/bindings/bus/sun50i-de2-bus.txt
index 87dfb33fb3be..b9d533717dff 100644
--- a/Documentation/devicetree/bindings/bus/sun50i-de2-bus.txt
+++ b/Documentation/devicetree/bindings/bus/sun50i-de2-bus.txt
@@ -1,11 +1,14 @@
-Device tree bindings for Allwinner A64 DE2 bus
+Device tree bindings for Allwinner DE2/3 bus
 
 The Allwinner A64 DE2 is on a special bus, which needs a SRAM region (SRAM C)
-to be claimed for enabling the access.
+to be claimed for enabling the access. The DE3 on Allwinner H6 is at the same
+situation, and the binding also applies.
 
 Required properties:
 
- - compatible: Should contain "allwinner,sun50i-a64-de2"
+ - compatible: Should be one of:
+   - "allwinner,sun50i-a64-de2"
+   - "allwinner,sun50i-h6-de3", 
"allwinner,sun50i-a64-de2"
  - reg:A resource specifier for the register space
  - #address-cells: Must be set to 1
  - #size-cells:Must be set to 1
-- 
2.19.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 15/28] drm/sun4i: Not all DW HDMI controllers has scrambled addresses

2018-11-04 Thread Jernej Skrabec
Currently supported Allwinner SoCs with DW HDMI controller have
scrambled addresses and read lock. However, that is not true in general.
For example, A80 and H6 have normal addresses and normal read access.

Move code for unscrambling addresses and unlocking read access to it's
own function and call it from init function.

Reviewed-by: Chen-Yu Tsai 
Signed-off-by: Jernej Skrabec 
---
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 23 +++
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 471993097ced..365cb5a9fb77 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -279,8 +279,21 @@ static const struct dw_hdmi_phy_ops sun8i_hdmi_phy_ops = {
.setup_hpd = _hdmi_phy_setup_hpd,
 };
 
+static void sun8i_hdmi_phy_unlock(struct sun8i_hdmi_phy *phy)
+{
+   /* enable read access to HDMI controller */
+   regmap_write(phy->regs, SUN8I_HDMI_PHY_READ_EN_REG,
+SUN8I_HDMI_PHY_READ_EN_MAGIC);
+
+   /* unscramble register offsets */
+   regmap_write(phy->regs, SUN8I_HDMI_PHY_UNSCRAMBLE_REG,
+SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC);
+}
+
 static void sun8i_hdmi_phy_init_a83t(struct sun8i_hdmi_phy *phy)
 {
+   sun8i_hdmi_phy_unlock(phy);
+
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
   SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK,
   SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK);
@@ -298,6 +311,8 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy 
*phy)
 {
unsigned int val;
 
+   sun8i_hdmi_phy_unlock(phy);
+
regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 0);
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
   SUN8I_HDMI_PHY_ANA_CFG1_ENBI,
@@ -372,14 +387,6 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy 
*phy)
 
 void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
 {
-   /* enable read access to HDMI controller */
-   regmap_write(phy->regs, SUN8I_HDMI_PHY_READ_EN_REG,
-SUN8I_HDMI_PHY_READ_EN_MAGIC);
-
-   /* unscramble register offsets */
-   regmap_write(phy->regs, SUN8I_HDMI_PHY_UNSCRAMBLE_REG,
-SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC);
-
phy->variant->phy_init(phy);
 }
 
-- 
2.19.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


  1   2   3   4   5   >