cec: convert remaining drivers to the new notifier API
Subsystems (9)
cover cec: convert remaining drivers to the new notifier API
This series updates remaining drivers in DRM to use new CEC notifier API.
Those complement the "cec: improve notifier support, add connector info" patch series and also replace 2 following patches from there:
- [PATCHv8 09/13] dw-hdmi: use cec_notifier_conn_(un)register
- [PATCHv9 12/13] tda998x: use cec_notifier_conn_(un)register
None of those changes were not tested on a real hardware.
Dariusz Marcinkiewicz (5):
drm: tda998x: use cec_notifier_conn_(un)register
drm: sti: use cec_notifier_conn_(un)register
drm: tegra: use cec_notifier_conn_(un)register
drm: dw-hdmi: use cec_notifier_conn_(un)register
drm: exynos: exynos_hdmi: use cec_notifier_conn_(un)register
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 32 +++++++++++++--------- drivers/gpu/drm/exynos/exynos_hdmi.c | 33 ++++++++++++++--------- drivers/gpu/drm/i2c/tda998x_drv.c | 27 ++++++++++++------- drivers/gpu/drm/sti/sti_hdmi.c | 20 +++++++++----- drivers/gpu/drm/tegra/output.c | 18 ++++++++----- 5 files changed, 81 insertions(+), 49 deletions(-)
Signature · 1 line
2.22.0.410.gd8fdbe21b5-goog
PATCH 1/5 drm: tda998x: use cec_notifier_conn_(un)register
Use the new cec_notifier_conn_(un)register() functions to (un)register the notifier for the HDMI connector, and fill in the cec_connector_info.
--- drivers/gpu/drm/i2c/tda998x_drv.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-)
drivers/gpu/drm/i2c/tda998x_drv.c +18 -9
@@ -794,9 +794,14 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data)if (lvl &CEC_RXSHPDLEV_HPD ) {tda998x_edid_delay_start (priv); }else { +struct cec_notifier *notify; +schedule_work (&priv->detect_work); -cec_notifier_set_phys_addr (priv->cec_notify, -CEC_PHYS_ADDR_INVALID ); + + notify =READ_ONCE (priv->cec_notify); +if (notify) +cec_notifier_set_phys_addr (notify, +CEC_PHYS_ADDR_INVALID ); } handled = true;
@@ -1253,6 +1258,8 @@ static int tda998x_connector_init(struct tda998x_priv *priv, struct drm_device *drm) {struct drm_connector *connector = &priv->connector; +struct cec_connector_info conn_info; +struct cec_notifier *notifier;int ret; connector->interlace_allowed =1 ;
@@ -1269,6 +1276,14 @@ static int tda998x_connector_init(struct tda998x_priv *priv,if (ret)return ret; +cec_fill_conn_info_from_drm (&conn_info, connector); + + notifier =cec_notifier_conn_register (priv->cec_glue.parent, +NULL , &conn_info); +if (!notifier) +return -ENOMEM ; +WRITE_ONCE (priv->cec_notify, notifier); +drm_connector_attach_encoder (&priv->connector, priv->bridge.encoder);
@@ -1651,7 +1666,7 @@ static void tda998x_destroy(struct device *dev)i2c_unregister_device (priv->cec);if (priv->cec_notify) -cec_notifier_put (priv->cec_notify); +cec_notifier_conn_unregister (priv->cec_notify); }static int tda998x_create (struct device *dev)
@@ -1776,12 +1791,6 @@ static int tda998x_create(struct device *dev)cec_write (priv,REG_CEC_RXSHPDINTENA ,CEC_RXSHPDLEV_HPD ); } - priv->cec_notify =cec_notifier_get (dev); -if (!priv->cec_notify) { - ret = -ENOMEM ; - goto fail; - } - priv->cec_glue.parent = dev; priv->cec_glue.data = priv; priv->cec_glue.init = tda998x_cec_hook_init;
Signature · 1 line
2.22.0.410.gd8fdbe21b5-goog
PATCH 2/5 drm: sti: use cec_notifier_conn_(un)register
In reply to Dariusz MarcinkiewiczUse the new cec_notifier_conn_(un)register() functions to (un)register the notifier for the HDMI connector, and fill in the cec_connector_info.
--- drivers/gpu/drm/sti/sti_hdmi.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
drivers/gpu/drm/sti/sti_hdmi.c +13 -7
@@ -1250,6 +1250,7 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)struct drm_device *drm_dev = data;struct drm_encoder *encoder;struct sti_hdmi_connector *connector; +struct cec_connector_info conn_info;struct drm_connector *drm_connector;struct drm_bridge *bridge;int err;
@@ -1310,6 +1311,14 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data) goto err_sysfs; } +cec_fill_conn_info_from_drm (&conn_info, drm_connector); + hdmi->notifier =cec_notifier_conn_register (&hdmi->dev,NULL , + &conn_info); +if (!hdmi->notifier) { + hdmi->drm_connector =NULL ; +return -ENOMEM ; + } +/* Enable default interrupts */ hdmi_write (hdmi,HDMI_DEFAULT_INT ,HDMI_INT_EN );
@@ -1323,6 +1332,10 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)static void sti_hdmi_unbind (struct device *dev,struct device *master,void *data) { +struct sti_hdmi *hdmi =dev_get_drvdata (dev); + +cec_notifier_set_phys_addr (hdmi->notifier,CEC_PHYS_ADDR_INVALID ); +cec_notifier_conn_unregister (hdmi->notifier); }static const struct component_ops sti_hdmi_ops = {
@@ -1428,10 +1441,6 @@ static int sti_hdmi_probe(struct platform_device *pdev) goto release_adapter; } - hdmi->notifier =cec_notifier_get (&pdev->dev); -if (!hdmi->notifier) - goto release_adapter; - hdmi->reset =devm_reset_control_get (dev,"hdmi" );/* Take hdmi out of reset */ if (!IS_ERR (hdmi->reset))
@@ -1451,14 +1460,11 @@ static int sti_hdmi_remove(struct platform_device *pdev) {struct sti_hdmi *hdmi =dev_get_drvdata (&pdev->dev); -cec_notifier_set_phys_addr (hdmi->notifier,CEC_PHYS_ADDR_INVALID ); -i2c_put_adapter (hdmi->ddc_adapt);if (hdmi->audio_pdev)platform_device_unregister (hdmi->audio_pdev);component_del (&pdev->dev, &sti_hdmi_ops); -cec_notifier_put (hdmi->notifier);return 0 ; }
Signature · 1 line
2.22.0.410.gd8fdbe21b5-goog
PATCH 3/5 drm: tegra: use cec_notifier_conn_(un)register
In reply to Dariusz MarcinkiewiczUse the new cec_notifier_conn_(un)register() functions to (un)register the notifier for the HDMI connector, and fill in the cec_connector_info.
--- drivers/gpu/drm/tegra/output.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
drivers/gpu/drm/tegra/output.c +11 -7
@@ -80,6 +80,9 @@ tegra_output_connector_detect(struct drm_connector *connector, bool force)void tegra_output_connector_destroy (struct drm_connector *connector) { +struct tegra_output *output =connector_to_output (connector); + +cec_notifier_conn_unregister (output->cec);drm_connector_unregister (connector);drm_connector_cleanup (connector); }
@@ -174,18 +177,11 @@ int tegra_output_probe(struct tegra_output *output)disable_irq (output->hpd_irq); } - output->cec =cec_notifier_get (output->dev); -if (!output->cec) -return -ENOMEM ; -return 0 ; }void tegra_output_remove (struct tegra_output *output) { -if (output->cec) -cec_notifier_put (output->cec); -if (gpio_is_valid (output->hpd_gpio)) {free_irq (output->hpd_irq, output);gpio_free (output->hpd_gpio);
@@ -197,6 +193,7 @@ void tegra_output_remove(struct tegra_output *output)int tegra_output_init (struct drm_device *drm,struct tegra_output *output) { +struct cec_connector_info conn_info;int err;if (output->panel) {
@@ -212,6 +209,13 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)if (gpio_is_valid (output->hpd_gpio))enable_irq (output->hpd_irq); +cec_fill_conn_info_from_drm (&conn_info, &output->connector); + + output->cec =cec_notifier_conn_register (output->dev,NULL , &conn_info); +if (!output->cec) +return -ENOMEM ; + +return 0 ; }
Signature · 1 line
2.22.0.410.gd8fdbe21b5-goog
PATCH 4/5 drm: dw-hdmi: use cec_notifier_conn_(un)register
In reply to Dariusz MarcinkiewiczUse the new cec_notifier_conn_(un)register() functions to (un)register the notifier for the HDMI connector, and fill in the cec_connector_info.
--- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 32 ++++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-)
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +19 -13
@@ -2118,6 +2118,8 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)struct dw_hdmi *hdmi = bridge->driver_private;struct drm_encoder *encoder = bridge->encoder;struct drm_connector *connector = &hdmi->connector; +struct cec_connector_info conn_info; +struct cec_notifier *notifier; connector->interlace_allowed =1 ; connector->polled =DRM_CONNECTOR_POLL_HPD ;
@@ -2129,6 +2131,13 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)drm_connector_attach_encoder (connector, encoder); +cec_fill_conn_info_from_drm (&conn_info, connector); + + notifier =cec_notifier_conn_register (hdmi->dev,NULL , &conn_info); +if (!notifier) +return -ENOMEM ; +WRITE_ONCE (hdmi->cec_notifier, notifier); +return 0 ; }
@@ -2295,9 +2304,15 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) phy_stat &HDMI_PHY_HPD , phy_stat & HDMI_PHY_RX_SENSE); -if ((phy_stat & (HDMI_PHY_RX_SENSE |HDMI_PHY_HPD )) ==0 ) -cec_notifier_set_phys_addr (hdmi->cec_notifier, -CEC_PHYS_ADDR_INVALID ); +if ((phy_stat & (HDMI_PHY_RX_SENSE |HDMI_PHY_HPD )) ==0 ) { +struct cec_notifier *notifer; + + notifer =READ_ONCE (hdmi->cec_notifier); +if (notifer) +cec_notifier_set_phys_addr ( + notifer, +CEC_PHYS_ADDR_INVALID ); + } }if (intr_stat &HDMI_IH_PHY_STAT0_HPD ) {
@@ -2600,12 +2615,6 @@ __dw_hdmi_probe(struct platform_device *pdev,if (ret) goto err_iahb; - hdmi->cec_notifier =cec_notifier_get (dev); -if (!hdmi->cec_notifier) { - ret = -ENOMEM ; - goto err_iahb; - } -/* * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator * N and cts values before enabling phy
@@ -2693,9 +2702,6 @@ __dw_hdmi_probe(struct platform_device *pdev, hdmi->ddc =NULL ; } -if (hdmi->cec_notifier) -cec_notifier_put (hdmi->cec_notifier); -clk_disable_unprepare (hdmi->iahb_clk);if (hdmi->cec_clk)clk_disable_unprepare (hdmi->cec_clk);
@@ -2718,7 +2724,7 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)hdmi_writeb (hdmi, ~0 ,HDMI_IH_MUTE_PHY_STAT0 );if (hdmi->cec_notifier) -cec_notifier_put (hdmi->cec_notifier); +cec_notifier_conn_unregister (hdmi->cec_notifier);clk_disable_unprepare (hdmi->iahb_clk);clk_disable_unprepare (hdmi->isfr_clk);
Signature · 1 line
2.22.0.410.gd8fdbe21b5-goog
kbuild test robot
build botRe: [PATCH 4/5] drm: dw-hdmi: use cec_notifier_conn_(un)register
I love your patch! Yet something to improve:
Hi Dariusz,
I love your patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v5.2-rc7]
[cannot apply to next-20190702]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Dariusz-Marcinkiewicz/cec-convert-remaining-drivers-to-the-new-notifier-API/20190702-213026
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 7.4.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.4.0 make.cross ARCH=ia64
If you fix the issue, kindly add following tag
All errors (new ones prefixed by >>):
drivers/gpu//drm/bridge/synopsys/dw-hdmi.c: In function 'dw_hdmi_bridge_attach':
>> drivers/gpu//drm/bridge/synopsys/dw-hdmi.c:2116:28: error: storage size of 'conn_info' isn't known
struct cec_connector_info conn_info;
^~~~~~~~~
>> drivers/gpu//drm/bridge/synopsys/dw-hdmi.c:2129:2: error: implicit declaration of function 'cec_fill_conn_info_from_drm' [-Werror=implicit-function-declaration]
cec_fill_conn_info_from_drm(&conn_info, connector);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/gpu//drm/bridge/synopsys/dw-hdmi.c:2131:13: error: implicit declaration of function 'cec_notifier_conn_register'; did you mean 'cec_notifier_unregister'? [-Werror=implicit-function-declaration]
notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info);
^~~~~~~~~~~~~~~~~~~~~~~~~~
cec_notifier_unregister
drivers/gpu//drm/bridge/synopsys/dw-hdmi.c:2116:28: warning: unused variable 'conn_info' [-Wunused-variable]
struct cec_connector_info conn_info;
^~~~~~~~~
drivers/gpu//drm/bridge/synopsys/dw-hdmi.c: In function '__dw_hdmi_remove':
>> drivers/gpu//drm/bridge/synopsys/dw-hdmi.c:2722:3: error: implicit declaration of function 'cec_notifier_conn_unregister'; did you mean 'cec_notifier_unregister'? [-Werror=implicit-function-declaration]
cec_notifier_conn_unregister(hdmi->cec_notifier);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
cec_notifier_unregistercc1: some warnings being treated as errors
vim +2116 drivers/gpu//drm/bridge/synopsys/dw-hdmi.c
2110
2111 static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
2112 {
2113 struct dw_hdmi *hdmi = bridge->driver_private;
2114 struct drm_encoder *encoder = bridge->encoder;
2115 struct drm_connector *connector = &hdmi->connector;
> 2116 struct cec_connector_info conn_info; 2117 struct cec_notifier *notifier; 2118 2119 connector->interlace_allowed = 1; 2120 connector->polled = DRM_CONNECTOR_POLL_HPD; 2121 2122 drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs); 2123 2124 drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs, 2125 DRM_MODE_CONNECTOR_HDMIA); 2126 2127 drm_connector_attach_encoder(connector, encoder); 2128 > 2129 cec_fill_conn_info_from_drm(&conn_info, connector); 2130 > 2131 notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info);
2132 if (!notifier)
2133 return -ENOMEM;
2134 WRITE_ONCE(hdmi->cec_notifier, notifier);
2135
2136 return 0;
2137 }
2138
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
PATCH 5/5 drm: exynos: exynos_hdmi: use cec_notifier_conn_(un)register
In reply to Dariusz MarcinkiewiczUse the new cec_notifier_conn_(un)register() functions to (un)register the notifier for the HDMI connector, and fill in the cec_connector_info.
--- drivers/gpu/drm/exynos/exynos_hdmi.c | 33 +++++++++++++++++----------- 1 file changed, 20 insertions(+), 13 deletions(-)
drivers/gpu/drm/exynos/exynos_hdmi.c +20 -13
@@ -858,6 +858,11 @@ static enum drm_connector_status hdmi_detect(struct drm_connector *connector,static void hdmi_connector_destroy (struct drm_connector *connector) { +struct hdmi_context *hdata =connector_to_hdmi (connector); + +cec_notifier_set_phys_addr (hdata->notifier,CEC_PHYS_ADDR_INVALID ); +cec_notifier_conn_unregister (hdata->notifier); +drm_connector_unregister (connector);drm_connector_cleanup (connector); }
@@ -941,6 +946,7 @@ static int hdmi_create_connector(struct drm_encoder *encoder) {struct hdmi_context *hdata =encoder_to_hdmi (encoder);struct drm_connector *connector = &hdata->connector; +struct cec_connector_info conn_info;int ret; connector->interlace_allowed = true;
@@ -963,6 +969,15 @@ static int hdmi_create_connector(struct drm_encoder *encoder)DRM_DEV_ERROR (hdata->dev,"Failed to attach bridge\n" ); } +cec_fill_conn_info_from_drm (&conn_info, connector); + + hdata->notifier =cec_notifier_conn_register (hdata->dev,NULL , + &conn_info); +if (hdata->notifier ==NULL ) { + ret = -ENOMEM ; +DRM_DEV_ERROR (hdata->dev,"Failed to allocate CEC notifier\n" ); + } +return ret; }
@@ -1534,8 +1549,9 @@ static void hdmi_disable(struct drm_encoder *encoder)*/ mutex_unlock (&hdata->mutex);cancel_delayed_work (&hdata->hotplug_work); -cec_notifier_set_phys_addr (hdata->notifier, -CEC_PHYS_ADDR_INVALID ); +if (hdata->notifier) +cec_notifier_set_phys_addr (hdata->notifier, +CEC_PHYS_ADDR_INVALID );return ; }
@@ -2012,12 +2028,6 @@ static int hdmi_probe(struct platform_device *pdev) } } - hdata->notifier =cec_notifier_get (&pdev->dev); -if (hdata->notifier ==NULL ) { - ret = -ENOMEM ; - goto err_hdmiphy; - } -pm_runtime_enable (dev); audio_infoframe = &hdata->audio.infoframe;
@@ -2029,7 +2039,7 @@ static int hdmi_probe(struct platform_device *pdev) ret =hdmi_register_audio_device (hdata);if (ret) - goto err_notifier_put; + goto err_runtime_disable; ret =component_add (&pdev->dev, &hdmi_component_ops);if (ret)
@@ -2040,8 +2050,7 @@ static int hdmi_probe(struct platform_device *pdev) err_unregister_audio:platform_device_unregister (hdata->audio.pdev); -err_notifier_put: -cec_notifier_put (hdata->notifier); +err_runtime_disable:pm_runtime_disable (dev); err_hdmiphy:
@@ -2060,12 +2069,10 @@ static int hdmi_remove(struct platform_device *pdev)struct hdmi_context *hdata =platform_get_drvdata (pdev);cancel_delayed_work_sync (&hdata->hotplug_work); -cec_notifier_set_phys_addr (hdata->notifier,CEC_PHYS_ADDR_INVALID );component_del (&pdev->dev, &hdmi_component_ops);platform_device_unregister (hdata->audio.pdev); -cec_notifier_put (hdata->notifier);pm_runtime_disable (&pdev->dev);if (!IS_ERR (hdata->reg_hdmi_en))
Signature · 1 line
2.22.0.410.gd8fdbe21b5-goog
kbuild test robot
build botRe: [PATCH 5/5] drm: exynos: exynos_hdmi: use cec_notifier_conn_(un)register
I love your patch! Yet something to improve:
Hi Dariusz,
I love your patch! Yet something to improve:
[auto build test ERROR on linus/master]
[cannot apply to v5.2-rc7 next-20190704]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Dariusz-Marcinkiewicz/cec-convert-remaining-drivers-to-the-new-notifier-API/20190702-213026
reproduce:
# apt-get install sparse
# sparse version:
make ARCH=x86_64 allmodconfig
make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'If you fix the issue, kindly add following tag
All errors (new ones prefixed by >>):
drivers/gpu/drm/i2c/tda998x_drv.c:1045:5: sparse: warning: symbol 'tda998x_audio_digital_mute' was not declared. Should it be static?
>> drivers/gpu/drm/i2c/tda998x_drv.c:1268:9: sparse: error: undefined identifier 'cec_fill_conn_info_from_drm' >> drivers/gpu/drm/i2c/tda998x_drv.c:1270:20: sparse: error: undefined identifier 'cec_notifier_conn_register' drivers/gpu/drm/i2c/tda998x_drv.c:1596:50: sparse: warning: incorrect type in argument 1 (different base types) drivers/gpu/drm/i2c/tda998x_drv.c:1596:50: sparse: expected restricted __be32 const [usertype] *p drivers/gpu/drm/i2c/tda998x_drv.c:1596:50: sparse: got unsigned int const [usertype] * drivers/gpu/drm/i2c/tda998x_drv.c:1597:52: sparse: warning: incorrect type in argument 1 (different base types) drivers/gpu/drm/i2c/tda998x_drv.c:1597:52: sparse: expected restricted __be32 const [usertype] *p drivers/gpu/drm/i2c/tda998x_drv.c:1597:52: sparse: got unsigned int const [usertype] * >> drivers/gpu/drm/i2c/tda998x_drv.c:1658:17: sparse: error: undefined identifier 'cec_notifier_conn_unregister' -- >> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c:2129:9: sparse: error: undefined identifier 'cec_fill_conn_info_from_drm' >> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c:2131:20: sparse: error: undefined identifier 'cec_notifier_conn_register' >> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c:2722:17: sparse: error: undefined identifier 'cec_notifier_conn_unregister'
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c:2476:30: sparse: warning: cast truncates bits from constant value (ffffff0d becomes d)
vim +/cec_fill_conn_info_from_drm +1268 drivers/gpu/drm/i2c/tda998x_drv.c
25576733ec6e05 Russell King 2016-10-23 1245
a2f75662b7c3db Russell King 2016-10-23 1246 static int tda998x_connector_init(struct tda998x_priv *priv,
a2f75662b7c3db Russell King 2016-10-23 1247 struct drm_device *drm)
a2f75662b7c3db Russell King 2016-10-23 1248 {
a2f75662b7c3db Russell King 2016-10-23 1249 struct drm_connector *connector = &priv->connector;
f070b4ca123f0c Dariusz Marcinkiewicz 2019-07-01 1250 struct cec_connector_info conn_info;
f070b4ca123f0c Dariusz Marcinkiewicz 2019-07-01 1251 struct cec_notifier *notifier;
a2f75662b7c3db Russell King 2016-10-23 1252 int ret;
a2f75662b7c3db Russell King 2016-10-23 1253
a2f75662b7c3db Russell King 2016-10-23 1254 connector->interlace_allowed = 1;
a2f75662b7c3db Russell King 2016-10-23 1255
a2f75662b7c3db Russell King 2016-10-23 1256 if (priv->hdmi->irq)
a2f75662b7c3db Russell King 2016-10-23 1257 connector->polled = DRM_CONNECTOR_POLL_HPD;
a2f75662b7c3db Russell King 2016-10-23 1258 else
a2f75662b7c3db Russell King 2016-10-23 1259 connector->polled = DRM_CONNECTOR_POLL_CONNECT |
a2f75662b7c3db Russell King 2016-10-23 1260 DRM_CONNECTOR_POLL_DISCONNECT;
a2f75662b7c3db Russell King 2016-10-23 1261
a2f75662b7c3db Russell King 2016-10-23 1262 drm_connector_helper_add(connector, &tda998x_connector_helper_funcs);
a2f75662b7c3db Russell King 2016-10-23 1263 ret = drm_connector_init(drm, connector, &tda998x_connector_funcs,
a2f75662b7c3db Russell King 2016-10-23 1264 DRM_MODE_CONNECTOR_HDMIA);
a2f75662b7c3db Russell King 2016-10-23 1265 if (ret)
a2f75662b7c3db Russell King 2016-10-23 1266 return ret;
a2f75662b7c3db Russell King 2016-10-23 1267
f070b4ca123f0c Dariusz Marcinkiewicz 2019-07-01 @1268 cec_fill_conn_info_from_drm(&conn_info, connector);
f070b4ca123f0c Dariusz Marcinkiewicz 2019-07-01 1269
f070b4ca123f0c Dariusz Marcinkiewicz 2019-07-01 @1270 notifier = cec_notifier_conn_register(priv->cec_glue.parent,
f070b4ca123f0c Dariusz Marcinkiewicz 2019-07-01 1271 NULL, &conn_info);
f070b4ca123f0c Dariusz Marcinkiewicz 2019-07-01 1272 if (!notifier)
f070b4ca123f0c Dariusz Marcinkiewicz 2019-07-01 1273 return -ENOMEM;
f070b4ca123f0c Dariusz Marcinkiewicz 2019-07-01 1274 WRITE_ONCE(priv->cec_notify, notifier);
f070b4ca123f0c Dariusz Marcinkiewicz 2019-07-01 1275
a7ccc5a43b829a Dave Airlie 2018-08-08 1276 drm_connector_attach_encoder(&priv->connector,
30bd8b862f5466 Russell King 2018-08-02 1277 priv->bridge.encoder);
a2f75662b7c3db Russell King 2016-10-23 1278
a2f75662b7c3db Russell King 2016-10-23 1279 return 0;
a2f75662b7c3db Russell King 2016-10-23 1280 }
a2f75662b7c3db Russell King 2016-10-23 1281
30bd8b862f5466 Russell King 2018-08-02 1282 /* DRM bridge functions */
e7792ce2da5ded Rob Clark 2013-01-08 1283
30bd8b862f5466 Russell King 2018-08-02 1284 static int tda998x_bridge_attach(struct drm_bridge *bridge)
e7792ce2da5ded Rob Clark 2013-01-08 1285 {
30bd8b862f5466 Russell King 2018-08-02 1286 struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
9525c4dd923f8f Russell King 2015-08-14 1287
30bd8b862f5466 Russell King 2018-08-02 1288 return tda998x_connector_init(priv, bridge->dev);
30bd8b862f5466 Russell King 2018-08-02 1289 }
e7792ce2da5ded Rob Clark 2013-01-08 1290
30bd8b862f5466 Russell King 2018-08-02 1291 static void tda998x_bridge_detach(struct drm_bridge *bridge)
30bd8b862f5466 Russell King 2018-08-02 1292 {
30bd8b862f5466 Russell King 2018-08-02 1293 struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
e7792ce2da5ded Rob Clark 2013-01-08 1294
30bd8b862f5466 Russell King 2018-08-02 1295 drm_connector_cleanup(&priv->connector);
30bd8b862f5466 Russell King 2018-08-02 1296 }
e7792ce2da5ded Rob Clark 2013-01-08 1297
b073a70ecd37bc Russell King 2018-08-02 1298 static enum drm_mode_status tda998x_bridge_mode_valid(struct drm_bridge *bridge,
b073a70ecd37bc Russell King 2018-08-02 1299 const struct drm_display_mode *mode)
b073a70ecd37bc Russell King 2018-08-02 1300 {
b073a70ecd37bc Russell King 2018-08-02 1301 /* TDA19988 dotclock can go up to 165MHz */
b073a70ecd37bc Russell King 2018-08-02 1302 struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
b073a70ecd37bc Russell King 2018-08-02 1303
b073a70ecd37bc Russell King 2018-08-02 1304 if (mode->clock > ((priv->rev == TDA19988) ? 165000 : 150000))
b073a70ecd37bc Russell King 2018-08-02 1305 return MODE_CLOCK_HIGH;
b073a70ecd37bc Russell King 2018-08-02 1306 if (mode->htotal >= BIT(13))
b073a70ecd37bc Russell King 2018-08-02 1307 return MODE_BAD_HVALUE;
b073a70ecd37bc Russell King 2018-08-02 1308 if (mode->vtotal >= BIT(11))
b073a70ecd37bc Russell King 2018-08-02 1309 return MODE_BAD_VVALUE;
b073a70ecd37bc Russell King 2018-08-02 1310 return MODE_OK;
b073a70ecd37bc Russell King 2018-08-02 1311 }
b073a70ecd37bc Russell King 2018-08-02 1312
30bd8b862f5466 Russell King 2018-08-02 1313 static void tda998x_bridge_enable(struct drm_bridge *bridge)
e7792ce2da5ded Rob Clark 2013-01-08 1314 {
30bd8b862f5466 Russell King 2018-08-02 1315 struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
30bd8b862f5466 Russell King 2018-08-02 1316
2c6e758332a4fd Peter Rosin 2018-08-02 1317 if (!priv->is_on) {
c4c11dd160a8cc Russell King 2013-08-14 1318 /* enable video ports, audio will be enabled later */
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1319 reg_write(priv, REG_ENA_VP_0, 0xff);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1320 reg_write(priv, REG_ENA_VP_1, 0xff);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1321 reg_write(priv, REG_ENA_VP_2, 0xff);
e7792ce2da5ded Rob Clark 2013-01-08 1322 /* set muxing after enabling ports: */
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1323 reg_write(priv, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1324 reg_write(priv, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1325 reg_write(priv, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
3cb43378d83e37 Russell King 2016-10-23 1326
3cb43378d83e37 Russell King 2016-10-23 1327 priv->is_on = true;
2c6e758332a4fd Peter Rosin 2018-08-02 1328 }
2c6e758332a4fd Peter Rosin 2018-08-02 1329 }
2c6e758332a4fd Peter Rosin 2018-08-02 1330
30bd8b862f5466 Russell King 2018-08-02 1331 static void tda998x_bridge_disable(struct drm_bridge *bridge)
2c6e758332a4fd Peter Rosin 2018-08-02 1332 {
30bd8b862f5466 Russell King 2018-08-02 1333 struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
30bd8b862f5466 Russell King 2018-08-02 1334
2c6e758332a4fd Peter Rosin 2018-08-02 1335 if (priv->is_on) {
db6aaf4d55f95d Russell King 2013-09-24 1336 /* disable video ports */
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1337 reg_write(priv, REG_ENA_VP_0, 0x00);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1338 reg_write(priv, REG_ENA_VP_1, 0x00);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1339 reg_write(priv, REG_ENA_VP_2, 0x00);
e7792ce2da5ded Rob Clark 2013-01-08 1340
3cb43378d83e37 Russell King 2016-10-23 1341 priv->is_on = false;
3cb43378d83e37 Russell King 2016-10-23 1342 }
e7792ce2da5ded Rob Clark 2013-01-08 1343 }
e7792ce2da5ded Rob Clark 2013-01-08 1344
30bd8b862f5466 Russell King 2018-08-02 1345 static void tda998x_bridge_mode_set(struct drm_bridge *bridge,
63f8f3badf799c Laurent Pinchart 2018-04-06 1346 const struct drm_display_mode *mode,
63f8f3badf799c Laurent Pinchart 2018-04-06 1347 const struct drm_display_mode *adjusted_mode)
e7792ce2da5ded Rob Clark 2013-01-08 1348 {
30bd8b862f5466 Russell King 2018-08-02 1349 struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
926a299c42e38b Russell King 2018-08-02 1350 unsigned long tmds_clock;
e66e03abf80f70 Russell King 2015-06-06 1351 u16 ref_pix, ref_line, n_pix, n_line;
e66e03abf80f70 Russell King 2015-06-06 1352 u16 hs_pix_s, hs_pix_e;
e66e03abf80f70 Russell King 2015-06-06 1353 u16 vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e;
e66e03abf80f70 Russell King 2015-06-06 1354 u16 vs2_pix_s, vs2_pix_e, vs2_line_s, vs2_line_e;
e66e03abf80f70 Russell King 2015-06-06 1355 u16 vwin1_line_s, vwin1_line_e;
e66e03abf80f70 Russell King 2015-06-06 1356 u16 vwin2_line_s, vwin2_line_e;
e66e03abf80f70 Russell King 2015-06-06 1357 u16 de_pix_s, de_pix_e;
e66e03abf80f70 Russell King 2015-06-06 1358 u8 reg, div, rep;
e7792ce2da5ded Rob Clark 2013-01-08 1359
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1360 /*
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1361 * Internally TDA998x is using ITU-R BT.656 style sync but
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1362 * we get VESA style sync. TDA998x is using a reference pixel
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1363 * relative to ITU to sync to the input frame and for output
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1364 * sync generation. Currently, we are using reference detection
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1365 * from HS/VS, i.e. REFPIX/REFLINE denote frame start sync point
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1366 * which is position of rising VS with coincident rising HS.
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1367 *
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1368 * Now there is some issues to take care of:
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1369 * - HDMI data islands require sync-before-active
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1370 * - TDA998x register values must be > 0 to be enabled
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1371 * - REFLINE needs an additional offset of +1
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1372 * - REFPIX needs an addtional offset of +1 for UYUV and +3 for RGB
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1373 *
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1374 * So we add +1 to all horizontal and vertical register values,
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1375 * plus an additional +3 for REFPIX as we are using RGB input only.
e7792ce2da5ded Rob Clark 2013-01-08 1376 */
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1377 n_pix = mode->htotal;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1378 n_line = mode->vtotal;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1379
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1380 hs_pix_e = mode->hsync_end - mode->hdisplay;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1381 hs_pix_s = mode->hsync_start - mode->hdisplay;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1382 de_pix_e = mode->htotal;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1383 de_pix_s = mode->htotal - mode->hdisplay;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1384 ref_pix = 3 + hs_pix_s;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1385
179f1aa407b466 Sebastian Hesselbarth 2013-08-14 1386 /*
179f1aa407b466 Sebastian Hesselbarth 2013-08-14 1387 * Attached LCD controllers may generate broken sync. Allow
179f1aa407b466 Sebastian Hesselbarth 2013-08-14 1388 * those to adjust the position of the rising VS edge by adding
179f1aa407b466 Sebastian Hesselbarth 2013-08-14 1389 * HSKEW to ref_pix.
179f1aa407b466 Sebastian Hesselbarth 2013-08-14 1390 */
179f1aa407b466 Sebastian Hesselbarth 2013-08-14 1391 if (adjusted_mode->flags & DRM_MODE_FLAG_HSKEW)
179f1aa407b466 Sebastian Hesselbarth 2013-08-14 1392 ref_pix += adjusted_mode->hskew;
179f1aa407b466 Sebastian Hesselbarth 2013-08-14 1393
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1394 if ((mode->flags & DRM_MODE_FLAG_INTERLACE) == 0) {
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1395 ref_line = 1 + mode->vsync_start - mode->vdisplay;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1396 vwin1_line_s = mode->vtotal - mode->vdisplay - 1;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1397 vwin1_line_e = vwin1_line_s + mode->vdisplay;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1398 vs1_pix_s = vs1_pix_e = hs_pix_s;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1399 vs1_line_s = mode->vsync_start - mode->vdisplay;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1400 vs1_line_e = vs1_line_s +
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1401 mode->vsync_end - mode->vsync_start;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1402 vwin2_line_s = vwin2_line_e = 0;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1403 vs2_pix_s = vs2_pix_e = 0;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1404 vs2_line_s = vs2_line_e = 0;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1405 } else {
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1406 ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1407 vwin1_line_s = (mode->vtotal - mode->vdisplay)/2;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1408 vwin1_line_e = vwin1_line_s + mode->vdisplay/2;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1409 vs1_pix_s = vs1_pix_e = hs_pix_s;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1410 vs1_line_s = (mode->vsync_start - mode->vdisplay)/2;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1411 vs1_line_e = vs1_line_s +
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1412 (mode->vsync_end - mode->vsync_start)/2;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1413 vwin2_line_s = vwin1_line_s + mode->vtotal/2;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1414 vwin2_line_e = vwin2_line_s + mode->vdisplay/2;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1415 vs2_pix_s = vs2_pix_e = hs_pix_s + mode->htotal/2;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1416 vs2_line_s = vs1_line_s + mode->vtotal/2 ;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1417 vs2_line_e = vs2_line_s +
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1418 (mode->vsync_end - mode->vsync_start)/2;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1419 }
e7792ce2da5ded Rob Clark 2013-01-08 1420
926a299c42e38b Russell King 2018-08-02 1421 tmds_clock = mode->clock;
926a299c42e38b Russell King 2018-08-02 1422
926a299c42e38b Russell King 2018-08-02 1423 /*
926a299c42e38b Russell King 2018-08-02 1424 * The divisor is power-of-2. The TDA9983B datasheet gives
926a299c42e38b Russell King 2018-08-02 1425 * this as ranges of Msample/s, which is 10x the TMDS clock:
926a299c42e38b Russell King 2018-08-02 1426 * 0 - 800 to 1500 Msample/s
926a299c42e38b Russell King 2018-08-02 1427 * 1 - 400 to 800 Msample/s
926a299c42e38b Russell King 2018-08-02 1428 * 2 - 200 to 400 Msample/s
926a299c42e38b Russell King 2018-08-02 1429 * 3 - as 2 above
926a299c42e38b Russell King 2018-08-02 1430 */
926a299c42e38b Russell King 2018-08-02 1431 for (div = 0; div < 3; div++)
926a299c42e38b Russell King 2018-08-02 1432 if (80000 >> div <= tmds_clock)
926a299c42e38b Russell King 2018-08-02 1433 break;
e7792ce2da5ded Rob Clark 2013-01-08 1434
2cae8e028ecb44 Russell King 2016-11-02 1435 mutex_lock(&priv->audio_mutex);
2cae8e028ecb44 Russell King 2016-11-02 1436
e7792ce2da5ded Rob Clark 2013-01-08 1437 /* mute the audio FIFO: */
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1438 reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
e7792ce2da5ded Rob Clark 2013-01-08 1439
e7792ce2da5ded Rob Clark 2013-01-08 1440 /* set HDMI HDCP mode off: */
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1441 reg_write(priv, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1442 reg_clear(priv, REG_TX33, TX33_HDMI);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1443 reg_write(priv, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(0));
e7792ce2da5ded Rob Clark 2013-01-08 1444
e7792ce2da5ded Rob Clark 2013-01-08 1445 /* no pre-filter or interpolator: */
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1446 reg_write(priv, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) |
e7792ce2da5ded Rob Clark 2013-01-08 1447 HVF_CNTRL_0_INTPOL(0));
9476ed2e3883b1 Russell King 2016-11-03 1448 reg_set(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_PREFILT);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1449 reg_write(priv, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1450 reg_write(priv, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) |
e7792ce2da5ded Rob Clark 2013-01-08 1451 VIP_CNTRL_4_BLC(0));
e7792ce2da5ded Rob Clark 2013-01-08 1452
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1453 reg_clear(priv, REG_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IZ);
a8b517e5312124 Jean-Francois Moine 2014-01-25 1454 reg_clear(priv, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR |
a8b517e5312124 Jean-Francois Moine 2014-01-25 1455 PLL_SERIAL_3_SRL_DE);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1456 reg_write(priv, REG_SERIALIZER, 0);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1457 reg_write(priv, REG_HVF_CNTRL_1, HVF_CNTRL_1_VQR(0));
e7792ce2da5ded Rob Clark 2013-01-08 1458
e7792ce2da5ded Rob Clark 2013-01-08 1459 /* TODO enable pixel repeat for pixel rates less than 25Msamp/s */
e7792ce2da5ded Rob Clark 2013-01-08 1460 rep = 0;
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1461 reg_write(priv, REG_RPT_CNTRL, 0);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1462 reg_write(priv, REG_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
e7792ce2da5ded Rob Clark 2013-01-08 1463 SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
e7792ce2da5ded Rob Clark 2013-01-08 1464
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1465 reg_write(priv, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
e7792ce2da5ded Rob Clark 2013-01-08 1466 PLL_SERIAL_2_SRL_PR(rep));
e7792ce2da5ded Rob Clark 2013-01-08 1467
e7792ce2da5ded Rob Clark 2013-01-08 1468 /* set color matrix bypass flag: */
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1469 reg_write(priv, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP |
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1470 MAT_CONTRL_MAT_SC(1));
9476ed2e3883b1 Russell King 2016-11-03 1471 reg_set(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_CSC);
e7792ce2da5ded Rob Clark 2013-01-08 1472
e7792ce2da5ded Rob Clark 2013-01-08 1473 /* set BIAS tmds value: */
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1474 reg_write(priv, REG_ANA_GENERAL, 0x09);
e7792ce2da5ded Rob Clark 2013-01-08 1475
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1476 /*
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1477 * Sync on rising HSYNC/VSYNC
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1478 */
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1479 reg = VIP_CNTRL_3_SYNC_HS;
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1480
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1481 /*
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1482 * TDA19988 requires high-active sync at input stage,
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1483 * so invert low-active sync provided by master encoder here
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1484 */
088d61d1fdfde5 Sebastian Hesselbarth 2013-08-14 1485 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1486 reg |= VIP_CNTRL_3_H_TGL;
e7792ce2da5ded Rob Clark 2013-01-08 1487 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1488 reg |= VIP_CNTRL_3_V_TGL;
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1489 reg_write(priv, REG_VIP_CNTRL_3, reg);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1490
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1491 reg_write(priv, REG_VIDFORMAT, 0x00);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1492 reg_write16(priv, REG_REFPIX_MSB, ref_pix);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1493 reg_write16(priv, REG_REFLINE_MSB, ref_line);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1494 reg_write16(priv, REG_NPIX_MSB, n_pix);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1495 reg_write16(priv, REG_NLINE_MSB, n_line);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1496 reg_write16(priv, REG_VS_LINE_STRT_1_MSB, vs1_line_s);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1497 reg_write16(priv, REG_VS_PIX_STRT_1_MSB, vs1_pix_s);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1498 reg_write16(priv, REG_VS_LINE_END_1_MSB, vs1_line_e);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1499 reg_write16(priv, REG_VS_PIX_END_1_MSB, vs1_pix_e);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1500 reg_write16(priv, REG_VS_LINE_STRT_2_MSB, vs2_line_s);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1501 reg_write16(priv, REG_VS_PIX_STRT_2_MSB, vs2_pix_s);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1502 reg_write16(priv, REG_VS_LINE_END_2_MSB, vs2_line_e);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1503 reg_write16(priv, REG_VS_PIX_END_2_MSB, vs2_pix_e);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1504 reg_write16(priv, REG_HS_PIX_START_MSB, hs_pix_s);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1505 reg_write16(priv, REG_HS_PIX_STOP_MSB, hs_pix_e);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1506 reg_write16(priv, REG_VWIN_START_1_MSB, vwin1_line_s);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1507 reg_write16(priv, REG_VWIN_END_1_MSB, vwin1_line_e);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1508 reg_write16(priv, REG_VWIN_START_2_MSB, vwin2_line_s);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1509 reg_write16(priv, REG_VWIN_END_2_MSB, vwin2_line_e);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1510 reg_write16(priv, REG_DE_START_MSB, de_pix_s);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1511 reg_write16(priv, REG_DE_STOP_MSB, de_pix_e);
e7792ce2da5ded Rob Clark 2013-01-08 1512
e7792ce2da5ded Rob Clark 2013-01-08 1513 if (priv->rev == TDA19988) {
e7792ce2da5ded Rob Clark 2013-01-08 1514 /* let incoming pixels fill the active space (if any) */
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1515 reg_write(priv, REG_ENABLE_SPACE, 0x00);
e7792ce2da5ded Rob Clark 2013-01-08 1516 }
e7792ce2da5ded Rob Clark 2013-01-08 1517
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1518 /*
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1519 * Always generate sync polarity relative to input sync and
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1520 * revert input stage toggled sync at output stage
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1521 */
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1522 reg = TBG_CNTRL_1_DWIN_DIS | TBG_CNTRL_1_TGL_EN;
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1523 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1524 reg |= TBG_CNTRL_1_H_TGL;
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1525 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1526 reg |= TBG_CNTRL_1_V_TGL;
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1527 reg_write(priv, REG_TBG_CNTRL_1, reg);
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1528
e7792ce2da5ded Rob Clark 2013-01-08 1529 /* must be last register set: */
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1530 reg_write(priv, REG_TBG_CNTRL_0, 0);
c4c11dd160a8cc Russell King 2013-08-14 1531
319e658c78befa Russell King 2016-10-23 1532 priv->tmds_clock = adjusted_mode->clock;
319e658c78befa Russell King 2016-10-23 1533
896a4130b8e60c Russell King 2016-10-23 1534 /* CEA-861B section 6 says that:
896a4130b8e60c Russell King 2016-10-23 1535 * CEA version 1 (CEA-861) has no support for infoframes.
896a4130b8e60c Russell King 2016-10-23 1536 * CEA version 2 (CEA-861A) supports version 1 AVI infoframes,
896a4130b8e60c Russell King 2016-10-23 1537 * and optional basic audio.
896a4130b8e60c Russell King 2016-10-23 1538 * CEA version 3 (CEA-861B) supports version 1 and 2 AVI infoframes,
896a4130b8e60c Russell King 2016-10-23 1539 * and optional digital audio, with audio infoframes.
896a4130b8e60c Russell King 2016-10-23 1540 *
896a4130b8e60c Russell King 2016-10-23 1541 * Since we only support generation of version 2 AVI infoframes,
896a4130b8e60c Russell King 2016-10-23 1542 * ignore CEA version 2 and below (iow, behave as if we're a
896a4130b8e60c Russell King 2016-10-23 1543 * CEA-861 source.)
896a4130b8e60c Russell King 2016-10-23 1544 */
896a4130b8e60c Russell King 2016-10-23 1545 priv->supports_infoframes = priv->connector.display_info.cea_rev >= 3;
896a4130b8e60c Russell King 2016-10-23 1546
896a4130b8e60c Russell King 2016-10-23 1547 if (priv->supports_infoframes) {
c4c11dd160a8cc Russell King 2013-08-14 1548 /* We need to turn HDMI HDCP stuff on to get audio through */
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1549 reg &= ~TBG_CNTRL_1_DWIN_DIS;
81b53a166f5cdf Jean-Francois Moine 2014-01-25 1550 reg_write(priv, REG_TBG_CNTRL_1, reg);
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1551 reg_write(priv, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(1));
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1552 reg_set(priv, REG_TX33, TX33_HDMI);
c4c11dd160a8cc Russell King 2013-08-14 1553
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1554 tda998x_write_avi(priv, adjusted_mode);
c4c11dd160a8cc Russell King 2013-08-14 1555
8f3f21f63c3625 Russell King 2016-11-02 1556 if (priv->audio_params.format != AFMT_UNUSED &&
8f3f21f63c3625 Russell King 2016-11-02 1557 priv->sink_has_audio)
319e658c78befa Russell King 2016-10-23 1558 tda998x_configure_audio(priv, &priv->audio_params);
95db3b255fde4e Jyri Sarha 2016-08-09 1559 }
319e658c78befa Russell King 2016-10-23 1560
319e658c78befa Russell King 2016-10-23 1561 mutex_unlock(&priv->audio_mutex);
c4c11dd160a8cc Russell King 2013-08-14 1562 }
e7792ce2da5ded Rob Clark 2013-01-08 1563
30bd8b862f5466 Russell King 2018-08-02 1564 static const struct drm_bridge_funcs tda998x_bridge_funcs = {
30bd8b862f5466 Russell King 2018-08-02 1565 .attach = tda998x_bridge_attach,
30bd8b862f5466 Russell King 2018-08-02 1566 .detach = tda998x_bridge_detach,
b073a70ecd37bc Russell King 2018-08-02 1567 .mode_valid = tda998x_bridge_mode_valid,
30bd8b862f5466 Russell King 2018-08-02 1568 .disable = tda998x_bridge_disable,
30bd8b862f5466 Russell King 2018-08-02 1569 .mode_set = tda998x_bridge_mode_set,
30bd8b862f5466 Russell King 2018-08-02 1570 .enable = tda998x_bridge_enable,
30bd8b862f5466 Russell King 2018-08-02 1571 };
a8f4d4d63739e4 Russell King 2014-02-07 1572
e7792ce2da5ded Rob Clark 2013-01-08 1573 /* I2C driver functions */
e7792ce2da5ded Rob Clark 2013-01-08 1574
7e567624dc5a44 Jyri Sarha 2016-08-09 1575 static int tda998x_get_audio_ports(struct tda998x_priv *priv,
7e567624dc5a44 Jyri Sarha 2016-08-09 1576 struct device_node *np)
7e567624dc5a44 Jyri Sarha 2016-08-09 1577 {
7e567624dc5a44 Jyri Sarha 2016-08-09 1578 const u32 *port_data;
7e567624dc5a44 Jyri Sarha 2016-08-09 1579 u32 size;
7e567624dc5a44 Jyri Sarha 2016-08-09 1580 int i;
7e567624dc5a44 Jyri Sarha 2016-08-09 1581
7e567624dc5a44 Jyri Sarha 2016-08-09 1582 port_data = of_get_property(np, "audio-ports", &size);
7e567624dc5a44 Jyri Sarha 2016-08-09 1583 if (!port_data)
7e567624dc5a44 Jyri Sarha 2016-08-09 1584 return 0;
7e567624dc5a44 Jyri Sarha 2016-08-09 1585
7e567624dc5a44 Jyri Sarha 2016-08-09 1586 size /= sizeof(u32);
7e567624dc5a44 Jyri Sarha 2016-08-09 1587 if (size > 2 * ARRAY_SIZE(priv->audio_port) || size % 2 != 0) {
7e567624dc5a44 Jyri Sarha 2016-08-09 1588 dev_err(&priv->hdmi->dev,
7e567624dc5a44 Jyri Sarha 2016-08-09 1589 "Bad number of elements in audio-ports dt-property\n");
7e567624dc5a44 Jyri Sarha 2016-08-09 1590 return -EINVAL;
7e567624dc5a44 Jyri Sarha 2016-08-09 1591 }
7e567624dc5a44 Jyri Sarha 2016-08-09 1592
7e567624dc5a44 Jyri Sarha 2016-08-09 1593 size /= 2;
7e567624dc5a44 Jyri Sarha 2016-08-09 1594
7e567624dc5a44 Jyri Sarha 2016-08-09 1595 for (i = 0; i < size; i++) {
7e567624dc5a44 Jyri Sarha 2016-08-09 1596 u8 afmt = be32_to_cpup(&port_data[2*i]);
7e567624dc5a44 Jyri Sarha 2016-08-09 1597 u8 ena_ap = be32_to_cpup(&port_data[2*i+1]);
7e567624dc5a44 Jyri Sarha 2016-08-09 1598
7e567624dc5a44 Jyri Sarha 2016-08-09 1599 if (afmt != AFMT_SPDIF && afmt != AFMT_I2S) {
7e567624dc5a44 Jyri Sarha 2016-08-09 1600 dev_err(&priv->hdmi->dev,
7e567624dc5a44 Jyri Sarha 2016-08-09 1601 "Bad audio format %u\n", afmt);
7e567624dc5a44 Jyri Sarha 2016-08-09 1602 return -EINVAL;
7e567624dc5a44 Jyri Sarha 2016-08-09 1603 }
7e567624dc5a44 Jyri Sarha 2016-08-09 1604
7e567624dc5a44 Jyri Sarha 2016-08-09 1605 priv->audio_port[i].format = afmt;
7e567624dc5a44 Jyri Sarha 2016-08-09 1606 priv->audio_port[i].config = ena_ap;
7e567624dc5a44 Jyri Sarha 2016-08-09 1607 }
7e567624dc5a44 Jyri Sarha 2016-08-09 1608
7e567624dc5a44 Jyri Sarha 2016-08-09 1609 if (priv->audio_port[0].format == priv->audio_port[1].format) {
7e567624dc5a44 Jyri Sarha 2016-08-09 1610 dev_err(&priv->hdmi->dev,
7e567624dc5a44 Jyri Sarha 2016-08-09 1611 "There can only be on I2S port and one SPDIF port\n");
7e567624dc5a44 Jyri Sarha 2016-08-09 1612 return -EINVAL;
7e567624dc5a44 Jyri Sarha 2016-08-09 1613 }
7e567624dc5a44 Jyri Sarha 2016-08-09 1614 return 0;
7e567624dc5a44 Jyri Sarha 2016-08-09 1615 }
7e567624dc5a44 Jyri Sarha 2016-08-09 1616
6c1187aaa2912f Russell King 2018-08-02 1617 static void tda998x_set_config(struct tda998x_priv *priv,
6c1187aaa2912f Russell King 2018-08-02 1618 const struct tda998x_encoder_params *p)
e7792ce2da5ded Rob Clark 2013-01-08 1619 {
6c1187aaa2912f Russell King 2018-08-02 1620 priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
6c1187aaa2912f Russell King 2018-08-02 1621 (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
6c1187aaa2912f Russell King 2018-08-02 1622 VIP_CNTRL_0_SWAP_B(p->swap_b) |
6c1187aaa2912f Russell King 2018-08-02 1623 (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
6c1187aaa2912f Russell King 2018-08-02 1624 priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
6c1187aaa2912f Russell King 2018-08-02 1625 (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
6c1187aaa2912f Russell King 2018-08-02 1626 VIP_CNTRL_1_SWAP_D(p->swap_d) |
6c1187aaa2912f Russell King 2018-08-02 1627 (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
6c1187aaa2912f Russell King 2018-08-02 1628 priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
6c1187aaa2912f Russell King 2018-08-02 1629 (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
6c1187aaa2912f Russell King 2018-08-02 1630 VIP_CNTRL_2_SWAP_F(p->swap_f) |
6c1187aaa2912f Russell King 2018-08-02 1631 (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
6c1187aaa2912f Russell King 2018-08-02 1632
6c1187aaa2912f Russell King 2018-08-02 1633 priv->audio_params = p->audio_params;
6c1187aaa2912f Russell King 2018-08-02 1634 }
6c1187aaa2912f Russell King 2018-08-02 1635
76767fdabadbea Russell King 2018-08-02 1636 static void tda998x_destroy(struct device *dev)
76767fdabadbea Russell King 2018-08-02 1637 {
76767fdabadbea Russell King 2018-08-02 1638 struct tda998x_priv *priv = dev_get_drvdata(dev);
76767fdabadbea Russell King 2018-08-02 1639
76767fdabadbea Russell King 2018-08-02 1640 drm_bridge_remove(&priv->bridge);
76767fdabadbea Russell King 2018-08-02 1641
76767fdabadbea Russell King 2018-08-02 1642 /* disable all IRQs and free the IRQ handler */
76767fdabadbea Russell King 2018-08-02 1643 cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
76767fdabadbea Russell King 2018-08-02 1644 reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
76767fdabadbea Russell King 2018-08-02 1645
76767fdabadbea Russell King 2018-08-02 1646 if (priv->audio_pdev)
76767fdabadbea Russell King 2018-08-02 1647 platform_device_unregister(priv->audio_pdev);
76767fdabadbea Russell King 2018-08-02 1648
76767fdabadbea Russell King 2018-08-02 1649 if (priv->hdmi->irq)
76767fdabadbea Russell King 2018-08-02 1650 free_irq(priv->hdmi->irq, priv);
76767fdabadbea Russell King 2018-08-02 1651
76767fdabadbea Russell King 2018-08-02 1652 del_timer_sync(&priv->edid_delay_timer);
76767fdabadbea Russell King 2018-08-02 1653 cancel_work_sync(&priv->detect_work);
76767fdabadbea Russell King 2018-08-02 1654
76767fdabadbea Russell King 2018-08-02 1655 i2c_unregister_device(priv->cec);
76767fdabadbea Russell King 2018-08-02 1656
76767fdabadbea Russell King 2018-08-02 1657 if (priv->cec_notify)
f070b4ca123f0c Dariusz Marcinkiewicz 2019-07-01 1658 cec_notifier_conn_unregister(priv->cec_notify);
76767fdabadbea Russell King 2018-08-02 1659 }
76767fdabadbea Russell King 2018-08-02 1660
2143adb04b357e Russell King 2018-08-02 1661 static int tda998x_create(struct device *dev)
e7792ce2da5ded Rob Clark 2013-01-08 1662 {
2143adb04b357e Russell King 2018-08-02 1663 struct i2c_client *client = to_i2c_client(dev);
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1664 struct device_node *np = client->dev.of_node;
7e8675f000bc7e Russell King 2016-10-05 1665 struct i2c_board_info cec_info;
2143adb04b357e Russell King 2018-08-02 1666 struct tda998x_priv *priv;
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1667 u32 video;
fb7544d7732f78 Russell King 2014-02-02 1668 int rev_lo, rev_hi, ret;
e7792ce2da5ded Rob Clark 2013-01-08 1669
2143adb04b357e Russell King 2018-08-02 1670 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
2143adb04b357e Russell King 2018-08-02 1671 if (!priv)
2143adb04b357e Russell King 2018-08-02 1672 return -ENOMEM;
2143adb04b357e Russell King 2018-08-02 1673
2143adb04b357e Russell King 2018-08-02 1674 dev_set_drvdata(dev, priv);
2143adb04b357e Russell King 2018-08-02 1675
d93ae190e2c952 Russell King 2016-11-17 1676 mutex_init(&priv->mutex); /* protect the page access */
d93ae190e2c952 Russell King 2016-11-17 1677 mutex_init(&priv->audio_mutex); /* protect access from audio thread */
7e8675f000bc7e Russell King 2016-10-05 1678 mutex_init(&priv->edid_mutex);
30bd8b862f5466 Russell King 2018-08-02 1679 INIT_LIST_HEAD(&priv->bridge.list);
d93ae190e2c952 Russell King 2016-11-17 1680 init_waitqueue_head(&priv->edid_delay_waitq);
d93ae190e2c952 Russell King 2016-11-17 1681 timer_setup(&priv->edid_delay_timer, tda998x_edid_delay_done, 0);
d93ae190e2c952 Russell King 2016-11-17 1682 INIT_WORK(&priv->detect_work, tda998x_detect_work);
ba300c1787f793 Russell King 2016-11-17 1683
5e74c22cd1e0f9 Russell King 2013-08-14 1684 priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
5e74c22cd1e0f9 Russell King 2013-08-14 1685 priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
5e74c22cd1e0f9 Russell King 2013-08-14 1686 priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
5e74c22cd1e0f9 Russell King 2013-08-14 1687
14e5b5889d7589 Russell King 2016-11-03 1688 /* CEC I2C address bound to TDA998x I2C addr by configuration pins */
14e5b5889d7589 Russell King 2016-11-03 1689 priv->cec_addr = 0x34 + (client->addr & 0x03);
2eb4c7b1e7f275 Jean-Francois Moine 2014-01-25 1690 priv->current_page = 0xff;
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1691 priv->hdmi = client;
ed9a84262a83ab Jean-Francois Moine 2014-11-29 1692
e7792ce2da5ded Rob Clark 2013-01-08 1693 /* wake up the device: */
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1694 cec_write(priv, REG_CEC_ENAMODS,
e7792ce2da5ded Rob Clark 2013-01-08 1695 CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI);
e7792ce2da5ded Rob Clark 2013-01-08 1696
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1697 tda998x_reset(priv);
e7792ce2da5ded Rob Clark 2013-01-08 1698
e7792ce2da5ded Rob Clark 2013-01-08 1699 /* read version: */
fb7544d7732f78 Russell King 2014-02-02 1700 rev_lo = reg_read(priv, REG_VERSION_LSB);
6a765c3fe54973 Russell King 2016-11-17 1701 if (rev_lo < 0) {
76767fdabadbea Russell King 2018-08-02 1702 dev_err(dev, "failed to read version: %d\n", rev_lo);
6a765c3fe54973 Russell King 2016-11-17 1703 return rev_lo;
6a765c3fe54973 Russell King 2016-11-17 1704 }
6a765c3fe54973 Russell King 2016-11-17 1705
fb7544d7732f78 Russell King 2014-02-02 1706 rev_hi = reg_read(priv, REG_VERSION_MSB);
6a765c3fe54973 Russell King 2016-11-17 1707 if (rev_hi < 0) {
76767fdabadbea Russell King 2018-08-02 1708 dev_err(dev, "failed to read version: %d\n", rev_hi);
6a765c3fe54973 Russell King 2016-11-17 1709 return rev_hi;
fb7544d7732f78 Russell King 2014-02-02 1710 }
fb7544d7732f78 Russell King 2014-02-02 1711
fb7544d7732f78 Russell King 2014-02-02 1712 priv->rev = rev_lo | rev_hi << 8;
e7792ce2da5ded Rob Clark 2013-01-08 1713
e7792ce2da5ded Rob Clark 2013-01-08 1714 /* mask off feature bits: */
e7792ce2da5ded Rob Clark 2013-01-08 1715 priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */
e7792ce2da5ded Rob Clark 2013-01-08 1716
e7792ce2da5ded Rob Clark 2013-01-08 1717 switch (priv->rev) {
b728fab7026b9d Jean-Francois Moine 2014-01-25 1718 case TDA9989N2:
76767fdabadbea Russell King 2018-08-02 1719 dev_info(dev, "found TDA9989 n2");
b728fab7026b9d Jean-Francois Moine 2014-01-25 1720 break;
b728fab7026b9d Jean-Francois Moine 2014-01-25 1721 case TDA19989:
76767fdabadbea Russell King 2018-08-02 1722 dev_info(dev, "found TDA19989");
b728fab7026b9d Jean-Francois Moine 2014-01-25 1723 break;
b728fab7026b9d Jean-Francois Moine 2014-01-25 1724 case TDA19989N2:
76767fdabadbea Russell King 2018-08-02 1725 dev_info(dev, "found TDA19989 n2");
b728fab7026b9d Jean-Francois Moine 2014-01-25 1726 break;
b728fab7026b9d Jean-Francois Moine 2014-01-25 1727 case TDA19988:
76767fdabadbea Russell King 2018-08-02 1728 dev_info(dev, "found TDA19988");
b728fab7026b9d Jean-Francois Moine 2014-01-25 1729 break;
e7792ce2da5ded Rob Clark 2013-01-08 1730 default:
76767fdabadbea Russell King 2018-08-02 1731 dev_err(dev, "found unsupported device: %04x\n", priv->rev);
6a765c3fe54973 Russell King 2016-11-17 1732 return -ENXIO;
e7792ce2da5ded Rob Clark 2013-01-08 1733 }
e7792ce2da5ded Rob Clark 2013-01-08 1734
e7792ce2da5ded Rob Clark 2013-01-08 1735 /* after reset, enable DDC: */
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1736 reg_write(priv, REG_DDC_DISABLE, 0x00);
e7792ce2da5ded Rob Clark 2013-01-08 1737
e7792ce2da5ded Rob Clark 2013-01-08 1738 /* set clock on DDC channel: */
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1739 reg_write(priv, REG_TX3, 39);
e7792ce2da5ded Rob Clark 2013-01-08 1740
e7792ce2da5ded Rob Clark 2013-01-08 1741 /* if necessary, disable multi-master: */
e7792ce2da5ded Rob Clark 2013-01-08 1742 if (priv->rev == TDA19989)
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1743 reg_set(priv, REG_I2C_MASTER, I2C_MASTER_DIS_MM);
e7792ce2da5ded Rob Clark 2013-01-08 1744
2f7f730a4f0fd3 Jean-Francois Moine 2014-01-25 1745 cec_write(priv, REG_CEC_FRO_IM_CLK_CTRL,
e7792ce2da5ded Rob Clark 2013-01-08 1746 CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
e7792ce2da5ded Rob Clark 2013-01-08 1747
ba8975f15bb93d Russell King 2017-03-11 1748 /* ensure interrupts are disabled */
ba8975f15bb93d Russell King 2017-03-11 1749 cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
ba8975f15bb93d Russell King 2017-03-11 1750
ba8975f15bb93d Russell King 2017-03-11 1751 /* clear pending interrupts */
ba8975f15bb93d Russell King 2017-03-11 1752 cec_read(priv, REG_CEC_RXSHPDINT);
ba8975f15bb93d Russell King 2017-03-11 1753 reg_read(priv, REG_INT_FLAGS_0);
ba8975f15bb93d Russell King 2017-03-11 1754 reg_read(priv, REG_INT_FLAGS_1);
ba8975f15bb93d Russell King 2017-03-11 1755 reg_read(priv, REG_INT_FLAGS_2);
ba8975f15bb93d Russell King 2017-03-11 1756
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1757 /* initialize the optional IRQ */
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1758 if (client->irq) {
ae81553c30ef86 Russell King 2016-11-03 1759 unsigned long irq_flags;
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1760
6833d26ef823b2 Jean-Francois Moine 2014-11-29 1761 /* init read EDID waitqueue and HDP work */
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1762 init_waitqueue_head(&priv->wq_edid);
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1763
ae81553c30ef86 Russell King 2016-11-03 1764 irq_flags =
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1765 irqd_get_trigger_type(irq_get_irq_data(client->irq));
7e8675f000bc7e Russell King 2016-10-05 1766
7e8675f000bc7e Russell King 2016-10-05 1767 priv->cec_glue.irq_flags = irq_flags;
7e8675f000bc7e Russell King 2016-10-05 1768
ae81553c30ef86 Russell King 2016-11-03 1769 irq_flags |= IRQF_SHARED | IRQF_ONESHOT;
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1770 ret = request_threaded_irq(client->irq, NULL,
ae81553c30ef86 Russell King 2016-11-03 1771 tda998x_irq_thread, irq_flags,
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1772 "tda998x", priv);
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1773 if (ret) {
76767fdabadbea Russell King 2018-08-02 1774 dev_err(dev, "failed to request IRQ#%u: %d\n",
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1775 client->irq, ret);
6a765c3fe54973 Russell King 2016-11-17 1776 goto err_irq;
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1777 }
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1778
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1779 /* enable HPD irq */
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1780 cec_write(priv, REG_CEC_RXSHPDINTENA, CEC_RXSHPDLEV_HPD);
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1781 }
12473b7d8e6074 Jean-Francois Moine 2014-01-25 1782
76767fdabadbea Russell King 2018-08-02 1783 priv->cec_glue.parent = dev;
7e8675f000bc7e Russell King 2016-10-05 1784 priv->cec_glue.data = priv;
7e8675f000bc7e Russell King 2016-10-05 1785 priv->cec_glue.init = tda998x_cec_hook_init;
7e8675f000bc7e Russell King 2016-10-05 1786 priv->cec_glue.exit = tda998x_cec_hook_exit;
7e8675f000bc7e Russell King 2016-10-05 1787 priv->cec_glue.open = tda998x_cec_hook_open;
7e8675f000bc7e Russell King 2016-10-05 1788 priv->cec_glue.release = tda998x_cec_hook_release;
7e8675f000bc7e Russell King 2016-10-05 1789
7e8675f000bc7e Russell King 2016-10-05 1790 /*
7e8675f000bc7e Russell King 2016-10-05 1791 * Some TDA998x are actually two I2C devices merged onto one piece
7e8675f000bc7e Russell King 2016-10-05 1792 * of silicon: TDA9989 and TDA19989 combine the HDMI transmitter
7e8675f000bc7e Russell King 2016-10-05 1793 * with a slightly modified TDA9950 CEC device. The CEC device
7e8675f000bc7e Russell King 2016-10-05 1794 * is at the TDA9950 address, with the address pins strapped across
7e8675f000bc7e Russell King 2016-10-05 1795 * to the TDA998x address pins. Hence, it always has the same
7e8675f000bc7e Russell King 2016-10-05 1796 * offset.
7e8675f000bc7e Russell King 2016-10-05 1797 */
7e8675f000bc7e Russell King 2016-10-05 1798 memset(&cec_info, 0, sizeof(cec_info));
7e8675f000bc7e Russell King 2016-10-05 1799 strlcpy(cec_info.type, "tda9950", sizeof(cec_info.type));
7e8675f000bc7e Russell King 2016-10-05 1800 cec_info.addr = priv->cec_addr;
7e8675f000bc7e Russell King 2016-10-05 1801 cec_info.platform_data = &priv->cec_glue;
7e8675f000bc7e Russell King 2016-10-05 1802 cec_info.irq = client->irq;
7e8675f000bc7e Russell King 2016-10-05 1803
7e8675f000bc7e Russell King 2016-10-05 1804 priv->cec = i2c_new_device(client->adapter, &cec_info);
101e996b8d3215 Russell King 2016-11-17 1805 if (!priv->cec) {
101e996b8d3215 Russell King 2016-11-17 1806 ret = -ENODEV;
101e996b8d3215 Russell King 2016-11-17 1807 goto fail;
101e996b8d3215 Russell King 2016-11-17 1808 }
101e996b8d3215 Russell King 2016-11-17 1809
e47826274e8871 Jean-Francois Moine 2014-01-25 1810 /* enable EDID read irq: */
e47826274e8871 Jean-Francois Moine 2014-01-25 1811 reg_set(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
e47826274e8871 Jean-Francois Moine 2014-01-25 1812
6c1187aaa2912f Russell King 2018-08-02 1813 if (np) {
7e567624dc5a44 Jyri Sarha 2016-08-09 1814 /* get the device tree parameters */
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1815 ret = of_property_read_u32(np, "video-ports", &video);
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1816 if (ret == 0) {
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1817 priv->vip_cntrl_0 = video >> 16;
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1818 priv->vip_cntrl_1 = video >> 8;
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1819 priv->vip_cntrl_2 = video;
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1820 }
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1821
7e567624dc5a44 Jyri Sarha 2016-08-09 1822 ret = tda998x_get_audio_ports(priv, np);
7e567624dc5a44 Jyri Sarha 2016-08-09 1823 if (ret)
7e567624dc5a44 Jyri Sarha 2016-08-09 1824 goto fail;
e7792ce2da5ded Rob Clark 2013-01-08 1825
7e567624dc5a44 Jyri Sarha 2016-08-09 1826 if (priv->audio_port[0].format != AFMT_UNUSED)
7e567624dc5a44 Jyri Sarha 2016-08-09 1827 tda998x_audio_codec_init(priv, &client->dev);
76767fdabadbea Russell King 2018-08-02 1828 } else if (dev->platform_data) {
76767fdabadbea Russell King 2018-08-02 1829 tda998x_set_config(priv, dev->platform_data);
6c1187aaa2912f Russell King 2018-08-02 1830 }
7e567624dc5a44 Jyri Sarha 2016-08-09 1831
30bd8b862f5466 Russell King 2018-08-02 1832 priv->bridge.funcs = &tda998x_bridge_funcs;
30bd8b862f5466 Russell King 2018-08-02 1833 #ifdef CONFIG_OF
30bd8b862f5466 Russell King 2018-08-02 1834 priv->bridge.of_node = dev->of_node;
30bd8b862f5466 Russell King 2018-08-02 1835 #endif
30bd8b862f5466 Russell King 2018-08-02 1836
30bd8b862f5466 Russell King 2018-08-02 1837 drm_bridge_add(&priv->bridge);
7e567624dc5a44 Jyri Sarha 2016-08-09 1838
7e567624dc5a44 Jyri Sarha 2016-08-09 1839 return 0;
6a765c3fe54973 Russell King 2016-11-17 1840
e7792ce2da5ded Rob Clark 2013-01-08 1841 fail:
2143adb04b357e Russell King 2018-08-02 1842 tda998x_destroy(dev);
6a765c3fe54973 Russell King 2016-11-17 1843 err_irq:
6a765c3fe54973 Russell King 2016-11-17 1844 return ret;
e7792ce2da5ded Rob Clark 2013-01-08 1845 }
e7792ce2da5ded Rob Clark 2013-01-08 1846
30bd8b862f5466 Russell King 2018-08-02 1847 /* DRM encoder functions */
c707c3619ca81f Russell King 2014-02-07 1848
c707c3619ca81f Russell King 2014-02-07 1849 static void tda998x_encoder_destroy(struct drm_encoder *encoder)
c707c3619ca81f Russell King 2014-02-07 1850 {
c707c3619ca81f Russell King 2014-02-07 1851 drm_encoder_cleanup(encoder);
c707c3619ca81f Russell King 2014-02-07 1852 }
c707c3619ca81f Russell King 2014-02-07 1853
c707c3619ca81f Russell King 2014-02-07 1854 static const struct drm_encoder_funcs tda998x_encoder_funcs = {
c707c3619ca81f Russell King 2014-02-07 1855 .destroy = tda998x_encoder_destroy,
c707c3619ca81f Russell King 2014-02-07 1856 };
c707c3619ca81f Russell King 2014-02-07 1857
30bd8b862f5466 Russell King 2018-08-02 1858 static int tda998x_encoder_init(struct device *dev, struct drm_device *drm)
c707c3619ca81f Russell King 2014-02-07 1859 {
30bd8b862f5466 Russell King 2018-08-02 1860 struct tda998x_priv *priv = dev_get_drvdata(dev);
e66e03abf80f70 Russell King 2015-06-06 1861 u32 crtcs = 0;
c707c3619ca81f Russell King 2014-02-07 1862 int ret;
c707c3619ca81f Russell King 2014-02-07 1863
5dbcf319b28327 Russell King 2014-06-15 1864 if (dev->of_node)
5dbcf319b28327 Russell King 2014-06-15 1865 crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
5dbcf319b28327 Russell King 2014-06-15 1866
5dbcf319b28327 Russell King 2014-06-15 1867 /* If no CRTCs were found, fall back to our old behaviour */
5dbcf319b28327 Russell King 2014-06-15 1868 if (crtcs == 0) {
5dbcf319b28327 Russell King 2014-06-15 1869 dev_warn(dev, "Falling back to first CRTC\n");
5dbcf319b28327 Russell King 2014-06-15 1870 crtcs = 1 << 0;
5dbcf319b28327 Russell King 2014-06-15 1871 }
5dbcf319b28327 Russell King 2014-06-15 1872
a3584f60f4898c Russell King 2015-08-14 1873 priv->encoder.possible_crtcs = crtcs;
c707c3619ca81f Russell King 2014-02-07 1874
a3584f60f4898c Russell King 2015-08-14 1875 ret = drm_encoder_init(drm, &priv->encoder, &tda998x_encoder_funcs,
13a3d91f17a5f7 Ville Syrjälä 2015-12-09 1876 DRM_MODE_ENCODER_TMDS, NULL);
c707c3619ca81f Russell King 2014-02-07 1877 if (ret)
c707c3619ca81f Russell King 2014-02-07 1878 goto err_encoder;
c707c3619ca81f Russell King 2014-02-07 1879
30bd8b862f5466 Russell King 2018-08-02 1880 ret = drm_bridge_attach(&priv->encoder, &priv->bridge, NULL);
c707c3619ca81f Russell King 2014-02-07 1881 if (ret)
30bd8b862f5466 Russell King 2018-08-02 1882 goto err_bridge;
c707c3619ca81f Russell King 2014-02-07 1883
c707c3619ca81f Russell King 2014-02-07 1884 return 0;
c707c3619ca81f Russell King 2014-02-07 1885
30bd8b862f5466 Russell King 2018-08-02 1886 err_bridge:
a3584f60f4898c Russell King 2015-08-14 1887 drm_encoder_cleanup(&priv->encoder);
c707c3619ca81f Russell King 2014-02-07 1888 err_encoder:
c707c3619ca81f Russell King 2014-02-07 1889 return ret;
c707c3619ca81f Russell King 2014-02-07 1890 }
c707c3619ca81f Russell King 2014-02-07 1891
30bd8b862f5466 Russell King 2018-08-02 1892 static int tda998x_bind(struct device *dev, struct device *master, void *data)
30bd8b862f5466 Russell King 2018-08-02 1893 {
30bd8b862f5466 Russell King 2018-08-02 1894 struct drm_device *drm = data;
30bd8b862f5466 Russell King 2018-08-02 1895
5a03f5346fedc8 Russell King 2018-08-02 1896 return tda998x_encoder_init(dev, drm);
30bd8b862f5466 Russell King 2018-08-02 1897 }
c707c3619ca81f Russell King 2014-02-07 1898
c707c3619ca81f Russell King 2014-02-07 1899 static void tda998x_unbind(struct device *dev, struct device *master,
c707c3619ca81f Russell King 2014-02-07 1900 void *data)
c707c3619ca81f Russell King 2014-02-07 1901 {
a3584f60f4898c Russell King 2015-08-14 1902 struct tda998x_priv *priv = dev_get_drvdata(dev);
c707c3619ca81f Russell King 2014-02-07 1903
a3584f60f4898c Russell King 2015-08-14 1904 drm_encoder_cleanup(&priv->encoder);
c707c3619ca81f Russell King 2014-02-07 1905 }
c707c3619ca81f Russell King 2014-02-07 1906
c707c3619ca81f Russell King 2014-02-07 1907 static const struct component_ops tda998x_ops = {
c707c3619ca81f Russell King 2014-02-07 1908 .bind = tda998x_bind,
c707c3619ca81f Russell King 2014-02-07 1909 .unbind = tda998x_unbind,
c707c3619ca81f Russell King 2014-02-07 1910 };
c707c3619ca81f Russell King 2014-02-07 1911
c707c3619ca81f Russell King 2014-02-07 1912 static int
c707c3619ca81f Russell King 2014-02-07 1913 tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
c707c3619ca81f Russell King 2014-02-07 1914 {
5a03f5346fedc8 Russell King 2018-08-02 1915 int ret;
5a03f5346fedc8 Russell King 2018-08-02 1916
14e5b5889d7589 Russell King 2016-11-03 1917 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
14e5b5889d7589 Russell King 2016-11-03 1918 dev_warn(&client->dev, "adapter does not support I2C\n");
14e5b5889d7589 Russell King 2016-11-03 1919 return -EIO;
14e5b5889d7589 Russell King 2016-11-03 1920 }
5a03f5346fedc8 Russell King 2018-08-02 1921
5a03f5346fedc8 Russell King 2018-08-02 1922 ret = tda998x_create(&client->dev);
5a03f5346fedc8 Russell King 2018-08-02 1923 if (ret)
5a03f5346fedc8 Russell King 2018-08-02 1924 return ret;
5a03f5346fedc8 Russell King 2018-08-02 1925
5a03f5346fedc8 Russell King 2018-08-02 1926 ret = component_add(&client->dev, &tda998x_ops);
5a03f5346fedc8 Russell King 2018-08-02 1927 if (ret)
5a03f5346fedc8 Russell King 2018-08-02 1928 tda998x_destroy(&client->dev);
5a03f5346fedc8 Russell King 2018-08-02 1929 return ret;
c707c3619ca81f Russell King 2014-02-07 1930 }
c707c3619ca81f Russell King 2014-02-07 1931
c707c3619ca81f Russell King 2014-02-07 1932 static int tda998x_remove(struct i2c_client *client)
c707c3619ca81f Russell King 2014-02-07 1933 {
c707c3619ca81f Russell King 2014-02-07 1934 component_del(&client->dev, &tda998x_ops);
5a03f5346fedc8 Russell King 2018-08-02 1935 tda998x_destroy(&client->dev);
c707c3619ca81f Russell King 2014-02-07 1936 return 0;
c707c3619ca81f Russell King 2014-02-07 1937 }
c707c3619ca81f Russell King 2014-02-07 1938
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1939 #ifdef CONFIG_OF
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1940 static const struct of_device_id tda998x_dt_ids[] = {
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1941 { .compatible = "nxp,tda998x", },
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1942 { }
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1943 };
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1944 MODULE_DEVICE_TABLE(of, tda998x_dt_ids);
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1945 #endif
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1946
b7f08c89a00ab9 Arvind Yadav 2017-08-19 1947 static const struct i2c_device_id tda998x_ids[] = {
e7792ce2da5ded Rob Clark 2013-01-08 1948 { "tda998x", 0 },
e7792ce2da5ded Rob Clark 2013-01-08 1949 { }
e7792ce2da5ded Rob Clark 2013-01-08 1950 };
e7792ce2da5ded Rob Clark 2013-01-08 1951 MODULE_DEVICE_TABLE(i2c, tda998x_ids);
e7792ce2da5ded Rob Clark 2013-01-08 1952
3d58e31888318e Russell King 2015-08-14 1953 static struct i2c_driver tda998x_driver = {
e7792ce2da5ded Rob Clark 2013-01-08 1954 .probe = tda998x_probe,
e7792ce2da5ded Rob Clark 2013-01-08 1955 .remove = tda998x_remove,
e7792ce2da5ded Rob Clark 2013-01-08 1956 .driver = {
e7792ce2da5ded Rob Clark 2013-01-08 1957 .name = "tda998x",
0d44ea190387e2 Jean-Francois Moine 2014-01-25 1958 .of_match_table = of_match_ptr(tda998x_dt_ids),
e7792ce2da5ded Rob Clark 2013-01-08 1959 },
e7792ce2da5ded Rob Clark 2013-01-08 1960 .id_table = tda998x_ids,
e7792ce2da5ded Rob Clark 2013-01-08 1961 };
e7792ce2da5ded Rob Clark 2013-01-08 1962
3d58e31888318e Russell King 2015-08-14 1963 module_i2c_driver(tda998x_driver);
e7792ce2da5ded Rob Clark 2013-01-08 1964
e7792ce2da5ded Rob Clark 2013-01-08 1965 MODULE_AUTHOR("Rob Clark <[email protected]");
e7792ce2da5ded Rob Clark 2013-01-08 1966 MODULE_DESCRIPTION("NXP Semiconductors TDA998X HDMI Encoder");
e7792ce2da5ded Rob Clark 2013-01-08 1967 MODULE_LICENSE("GPL");:::::: The code at line 1268 was first introduced by commit
:::::: f070b4ca123f0c4cedefc309ce2739131ca89750 drm: tda998x: use cec_notifier_conn_(un)register
:::::: TO: Dariusz Marcinkiewicz <[email protected]> :::::: CC: 0day robot <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation