From mboxrd@z Thu Jan 1 00:00:00 1970 From: moinejf@free.fr (Jean-Francois Moine) Date: Thu, 9 Jan 2014 12:03:24 +0100 Subject: [PATCH v2 12/28] drm/i2c: tda998x: add DT support Message-ID: <20140109120324.4e2c8aca@armhf> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org This patch adds DT support to the tda998x. As a side effect, now, the audio sample rate is always 48kHz and the audio clock is always set. Signed-off-by: Jean-Francois Moine --- .../devicetree/bindings/drm/i2c/tda998x.txt | 16 ++++++ drivers/gpu/drm/i2c/tda998x_drv.c | 66 ++++++++++++++++------ 2 file changed, 66 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/drm/i2c/tda998x.txt b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt new file mode 100644 index 0000000..f07339e1 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt @@ -0,0 +1,16 @@ +Device-Tree bindings for the NXP TDA998x HDMI transmitter + +Required properties; + - compatible: must be "nxp,tda998x" + +Optional properties: + - video-ports: 24 bits value - default: <0x230145> + +Example: + + tda998x: hdmi-encoder { + compatible = "nxp,tda998x"; + reg = <0x70>; + pinctrl-0 = <&pmx_camera>; + pinctrl-names = "default"; + }; diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 2ba0355..b87802f 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -28,17 +28,22 @@ #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) +#define AUDIO_SAMPLE 48 /* 48 kHz */ + struct tda998x_priv { struct i2c_client *cec; struct i2c_client *hdmi; uint16_t rev; uint8_t current_page; - int dpms; + u8 dpms; bool is_hdmi_sink; u8 vip_cntrl_0; u8 vip_cntrl_1; u8 vip_cntrl_2; - struct tda998x_encoder_params params; + + u8 audio_type; /* audio type */ + u8 audio_frame[6]; + u32 audio_port; }; #define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv) @@ -539,7 +544,7 @@ tda998x_write_if(struct tda998x_priv *priv, uint8_t bit, uint16_t addr, } static void -tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p) +tda998x_write_aif(struct tda998x_priv *priv) { u8 buf[PB(HDMI_AUDIO_INFOFRAME_SIZE) + 1]; @@ -547,10 +552,10 @@ tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p) buf[HB(0)] = HDMI_INFOFRAME_TYPE_AUDIO; buf[HB(1)] = 0x01; buf[HB(2)] = HDMI_AUDIO_INFOFRAME_SIZE; - buf[PB(1)] = p->audio_frame[1] & 0x07; /* CC */ - buf[PB(2)] = p->audio_frame[2] & 0x1c; /* SF */ - buf[PB(4)] = p->audio_frame[4]; - buf[PB(5)] = p->audio_frame[5] & 0xf8; /* DM_INH + LSV */ + buf[PB(1)] = priv->audio_frame[1] & 0x07; /* CC */ + buf[PB(2)] = priv->audio_frame[2] & 0x1c; /* SF */ + buf[PB(4)] = priv->audio_frame[4]; + buf[PB(5)] = priv->audio_frame[5] & 0xf8; /* DM_INH + LSV */ tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf, sizeof(buf)); @@ -586,17 +591,17 @@ static void tda998x_audio_mute(struct tda998x_priv *priv, bool on) static void tda998x_configure_audio(struct tda998x_priv *priv, - struct drm_display_mode *mode, struct tda998x_encoder_params *p) + struct drm_display_mode *mode) { uint8_t buf[6], clksel_aip, clksel_fs, ca_i2s, cts_n, adiv; uint32_t n; /* Enable audio ports */ - reg_write(priv, REG_ENA_AP, p->audio_cfg); - reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg); + reg_write(priv, REG_ENA_AP, priv->audio_port); + reg_write(priv, REG_ENA_ACLK, 0x01); /* enable clock */ /* Set audio input source */ - switch (p->audio_format) { + switch (priv->audio_type) { case AFMT_SPDIF: reg_write(priv, REG_MUX_AP, 0x40); clksel_aip = AIP_CLKSEL_AIP(0); @@ -644,7 +649,7 @@ tda998x_configure_audio(struct tda998x_priv *priv, * This is the approximate value of N, which happens to be * the recommended values for non-coherent clocks. */ - n = 128 * p->audio_sample_rate / 1000; + n = 128 * AUDIO_SAMPLE; /* acr_n = 128 * sample_rate / 1000 */ /* Write the CTS and N values */ buf[0] = 0x44; @@ -674,7 +679,7 @@ tda998x_configure_audio(struct tda998x_priv *priv, tda998x_audio_mute(priv, false); /* Write the audio information packet */ - tda998x_write_aif(priv, p); + tda998x_write_aif(priv); } /* DRM encoder functions */ @@ -698,7 +703,13 @@ tda998x_encoder_set_config(struct drm_encoder *encoder, void *params) VIP_CNTRL_2_SWAP_F(p->swap_f) | (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0); - priv->params = *p; + memcpy(priv->audio_frame, p->audio_frame, + sizeof priv->audio_frame); + + if (p->audio_cfg) { + priv->audio_port = p->audio_cfg; + priv->audio_type = p->audio_format; + } } static void @@ -947,8 +958,8 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, tda998x_write_avi(priv, mode); - if (priv->params.audio_cfg) - tda998x_configure_audio(priv, mode, &priv->params); + if (priv->audio_type) + tda998x_configure_audio(priv, mode); } } @@ -1157,6 +1168,8 @@ tda998x_encoder_init(struct i2c_client *client, struct drm_encoder_slave *encoder_slave) { struct tda998x_priv *priv; + struct device_node *np = client->dev.of_node; + u32 video; int ret; priv = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -1166,6 +1179,7 @@ tda998x_encoder_init(struct i2c_client *client, priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3); priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1); priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5); + priv->audio_frame[1] = 1; /* channels - 1 */ priv->current_page = 0xff; priv->hdmi = client; @@ -1225,6 +1239,17 @@ tda998x_encoder_init(struct i2c_client *client, cec_write(priv, REG_CEC_FRO_IM_CLK_CTRL, CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL); + if (!np) + return 0; /* non-DT */ + + /* get the optional video properties */ + ret = of_property_read_u32(np, "video-ports", &video); + if (ret == 0) { + priv->vip_cntrl_0 = video >> 16; + priv->vip_cntrl_1 = video >> 8; + priv->vip_cntrl_2 = video; + } + return 0; fail: @@ -1239,6 +1264,14 @@ fail: return -ENXIO; } +#ifdef CONFIG_OF +static const struct of_device_id tda998x_dt_ids[] = { + { .compatible = "nxp,tda998x", }, + { } +}; +MODULE_DEVICE_TABLE(of, tda998x_dt_ids); +#endif + static struct i2c_device_id tda998x_ids[] = { { "tda998x", 0 }, { } @@ -1251,6 +1284,7 @@ static struct drm_i2c_encoder_driver tda998x_driver = { .remove = tda998x_remove, .driver = { .name = "tda998x", + .of_match_table = of_match_ptr(tda998x_dt_ids), }, .id_table = tda998x_ids, }, -- Ken ar c'henta? | ** Breizh ha Linux atav! ** Jef | http://moinejf.free.fr/ From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jean-Francois Moine Subject: [PATCH v2 12/28] drm/i2c: tda998x: add DT support Date: Thu, 9 Jan 2014 12:03:24 +0100 Message-ID: <20140109120324.4e2c8aca@armhf> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org To: dri-devel@lists.freedesktop.org Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org List-Id: devicetree@vger.kernel.org VGhpcyBwYXRjaCBhZGRzIERUIHN1cHBvcnQgdG8gdGhlIHRkYTk5OHguCgpBcyBhIHNpZGUgZWZm ZWN0LCBub3csIHRoZSBhdWRpbyBzYW1wbGUgcmF0ZSBpcyBhbHdheXMgNDhrSHogYW5kIHRoZQph dWRpbyBjbG9jayBpcyBhbHdheXMgc2V0LgoKU2lnbmVkLW9mZi1ieTogSmVhbi1GcmFuY29pcyBN b2luZSA8bW9pbmVqZkBmcmVlLmZyPgotLS0KIC4uLi9kZXZpY2V0cmVlL2JpbmRpbmdzL2RybS9p MmMvdGRhOTk4eC50eHQgfCAxNiArKysrKysKIGRyaXZlcnMvZ3B1L2RybS9pMmMvdGRhOTk4eF9k cnYuYyAgICAgICAgICAgfCA2NiArKysrKysrKysrKysrKysrLS0tLS0tCiAyIGZpbGUgY2hhbmdl ZCwgNjYgaW5zZXJ0aW9ucygrKSwgMTYgZGVsZXRpb25zKC0pCgpkaWZmIC0tZ2l0IGEvRG9jdW1l bnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2RybS9pMmMvdGRhOTk4eC50eHQgYi9Eb2N1bWVu dGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvZHJtL2kyYy90ZGE5OTh4LnR4dApuZXcgZmlsZSBt b2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi5mMDczMzllMQotLS0gL2Rldi9udWxsCisrKyBiL0Rv Y3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9kcm0vaTJjL3RkYTk5OHgudHh0CkBAIC0w LDAgKzEsMTYgQEAKK0RldmljZS1UcmVlIGJpbmRpbmdzIGZvciB0aGUgTlhQIFREQTk5OHggSERN SSB0cmFuc21pdHRlcgorCitSZXF1aXJlZCBwcm9wZXJ0aWVzOworICAtIGNvbXBhdGlibGU6IG11 c3QgYmUgIm54cCx0ZGE5OTh4IgorCitPcHRpb25hbCBwcm9wZXJ0aWVzOgorICAtIHZpZGVvLXBv cnRzOiAyNCBiaXRzIHZhbHVlIC0gZGVmYXVsdDogPDB4MjMwMTQ1PgorCitFeGFtcGxlOgorCisJ dGRhOTk4eDogaGRtaS1lbmNvZGVyIHsKKwkJY29tcGF0aWJsZSA9ICJueHAsdGRhOTk4eCI7CisJ CXJlZyA9IDwweDcwPjsKKwkJcGluY3RybC0wID0gPCZwbXhfY2FtZXJhPjsKKwkJcGluY3RybC1u YW1lcyA9ICJkZWZhdWx0IjsKKwl9OwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2kyYy90 ZGE5OTh4X2Rydi5jIGIvZHJpdmVycy9ncHUvZHJtL2kyYy90ZGE5OTh4X2Rydi5jCmluZGV4IDJi YTAzNTUuLmI4NzgwMmYgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvZ3B1L2RybS9pMmMvdGRhOTk4eF9k cnYuYworKysgYi9kcml2ZXJzL2dwdS9kcm0vaTJjL3RkYTk5OHhfZHJ2LmMKQEAgLTI4LDE3ICsy OCwyMiBAQAogCiAjZGVmaW5lIERCRyhmbXQsIC4uLikgRFJNX0RFQlVHKGZtdCJcbiIsICMjX19W QV9BUkdTX18pCiAKKyNkZWZpbmUgQVVESU9fU0FNUExFIDQ4CQkvKiA0OCBrSHogKi8KKwogc3Ry dWN0IHRkYTk5OHhfcHJpdiB7CiAJc3RydWN0IGkyY19jbGllbnQgKmNlYzsKIAlzdHJ1Y3QgaTJj X2NsaWVudCAqaGRtaTsKIAl1aW50MTZfdCByZXY7CiAJdWludDhfdCBjdXJyZW50X3BhZ2U7Ci0J aW50IGRwbXM7CisJdTggZHBtczsKIAlib29sIGlzX2hkbWlfc2luazsKIAl1OCB2aXBfY250cmxf MDsKIAl1OCB2aXBfY250cmxfMTsKIAl1OCB2aXBfY250cmxfMjsKLQlzdHJ1Y3QgdGRhOTk4eF9l bmNvZGVyX3BhcmFtcyBwYXJhbXM7CisKKwl1OCBhdWRpb190eXBlOwkJLyogYXVkaW8gdHlwZSAq LworCXU4IGF1ZGlvX2ZyYW1lWzZdOworCXUzMiBhdWRpb19wb3J0OwogfTsKIAogI2RlZmluZSB0 b190ZGE5OTh4X3ByaXYoeCkgICgoc3RydWN0IHRkYTk5OHhfcHJpdiAqKXRvX2VuY29kZXJfc2xh dmUoeCktPnNsYXZlX3ByaXYpCkBAIC01MzksNyArNTQ0LDcgQEAgdGRhOTk4eF93cml0ZV9pZihz dHJ1Y3QgdGRhOTk4eF9wcml2ICpwcml2LCB1aW50OF90IGJpdCwgdWludDE2X3QgYWRkciwKIH0K IAogc3RhdGljIHZvaWQKLXRkYTk5OHhfd3JpdGVfYWlmKHN0cnVjdCB0ZGE5OTh4X3ByaXYgKnBy aXYsIHN0cnVjdCB0ZGE5OTh4X2VuY29kZXJfcGFyYW1zICpwKQordGRhOTk4eF93cml0ZV9haWYo c3RydWN0IHRkYTk5OHhfcHJpdiAqcHJpdikKIHsKIAl1OCBidWZbUEIoSERNSV9BVURJT19JTkZP RlJBTUVfU0laRSkgKyAxXTsKIApAQCAtNTQ3LDEwICs1NTIsMTAgQEAgdGRhOTk4eF93cml0ZV9h aWYoc3RydWN0IHRkYTk5OHhfcHJpdiAqcHJpdiwgc3RydWN0IHRkYTk5OHhfZW5jb2Rlcl9wYXJh bXMgKnApCiAJYnVmW0hCKDApXSA9IEhETUlfSU5GT0ZSQU1FX1RZUEVfQVVESU87CiAJYnVmW0hC KDEpXSA9IDB4MDE7CiAJYnVmW0hCKDIpXSA9IEhETUlfQVVESU9fSU5GT0ZSQU1FX1NJWkU7Ci0J YnVmW1BCKDEpXSA9IHAtPmF1ZGlvX2ZyYW1lWzFdICYgMHgwNzsgLyogQ0MgKi8KLQlidWZbUEIo MildID0gcC0+YXVkaW9fZnJhbWVbMl0gJiAweDFjOyAvKiBTRiAqLwotCWJ1ZltQQig0KV0gPSBw LT5hdWRpb19mcmFtZVs0XTsKLQlidWZbUEIoNSldID0gcC0+YXVkaW9fZnJhbWVbNV0gJiAweGY4 OyAvKiBETV9JTkggKyBMU1YgKi8KKwlidWZbUEIoMSldID0gcHJpdi0+YXVkaW9fZnJhbWVbMV0g JiAweDA3OyAvKiBDQyAqLworCWJ1ZltQQigyKV0gPSBwcml2LT5hdWRpb19mcmFtZVsyXSAmIDB4 MWM7IC8qIFNGICovCisJYnVmW1BCKDQpXSA9IHByaXYtPmF1ZGlvX2ZyYW1lWzRdOworCWJ1ZltQ Qig1KV0gPSBwcml2LT5hdWRpb19mcmFtZVs1XSAmIDB4Zjg7IC8qIERNX0lOSCArIExTViAqLwog CiAJdGRhOTk4eF93cml0ZV9pZihwcml2LCBESVBfSUZfRkxBR1NfSUY0LCBSRUdfSUY0X0hCMCwg YnVmLAogCQkJIHNpemVvZihidWYpKTsKQEAgLTU4NiwxNyArNTkxLDE3IEBAIHN0YXRpYyB2b2lk IHRkYTk5OHhfYXVkaW9fbXV0ZShzdHJ1Y3QgdGRhOTk4eF9wcml2ICpwcml2LCBib29sIG9uKQog CiBzdGF0aWMgdm9pZAogdGRhOTk4eF9jb25maWd1cmVfYXVkaW8oc3RydWN0IHRkYTk5OHhfcHJp diAqcHJpdiwKLQkJc3RydWN0IGRybV9kaXNwbGF5X21vZGUgKm1vZGUsIHN0cnVjdCB0ZGE5OTh4 X2VuY29kZXJfcGFyYW1zICpwKQorCQlzdHJ1Y3QgZHJtX2Rpc3BsYXlfbW9kZSAqbW9kZSkKIHsK IAl1aW50OF90IGJ1Zls2XSwgY2xrc2VsX2FpcCwgY2xrc2VsX2ZzLCBjYV9pMnMsIGN0c19uLCBh ZGl2OwogCXVpbnQzMl90IG47CiAKIAkvKiBFbmFibGUgYXVkaW8gcG9ydHMgKi8KLQlyZWdfd3Jp dGUocHJpdiwgUkVHX0VOQV9BUCwgcC0+YXVkaW9fY2ZnKTsKLQlyZWdfd3JpdGUocHJpdiwgUkVH X0VOQV9BQ0xLLCBwLT5hdWRpb19jbGtfY2ZnKTsKKwlyZWdfd3JpdGUocHJpdiwgUkVHX0VOQV9B UCwgcHJpdi0+YXVkaW9fcG9ydCk7CisJcmVnX3dyaXRlKHByaXYsIFJFR19FTkFfQUNMSywgMHgw MSk7CS8qIGVuYWJsZSBjbG9jayAqLwogCiAJLyogU2V0IGF1ZGlvIGlucHV0IHNvdXJjZSAqLwot CXN3aXRjaCAocC0+YXVkaW9fZm9ybWF0KSB7CisJc3dpdGNoIChwcml2LT5hdWRpb190eXBlKSB7 CiAJY2FzZSBBRk1UX1NQRElGOgogCQlyZWdfd3JpdGUocHJpdiwgUkVHX01VWF9BUCwgMHg0MCk7 CiAJCWNsa3NlbF9haXAgPSBBSVBfQ0xLU0VMX0FJUCgwKTsKQEAgLTY0NCw3ICs2NDksNyBAQCB0 ZGE5OTh4X2NvbmZpZ3VyZV9hdWRpbyhzdHJ1Y3QgdGRhOTk4eF9wcml2ICpwcml2LAogCSAqIFRo aXMgaXMgdGhlIGFwcHJveGltYXRlIHZhbHVlIG9mIE4sIHdoaWNoIGhhcHBlbnMgdG8gYmUKIAkg KiB0aGUgcmVjb21tZW5kZWQgdmFsdWVzIGZvciBub24tY29oZXJlbnQgY2xvY2tzLgogCSAqLwot CW4gPSAxMjggKiBwLT5hdWRpb19zYW1wbGVfcmF0ZSAvIDEwMDA7CisJbiA9IDEyOCAqIEFVRElP X1NBTVBMRTsJCS8qIGFjcl9uID0gMTI4ICogc2FtcGxlX3JhdGUgLyAxMDAwICovCiAKIAkvKiBX cml0ZSB0aGUgQ1RTIGFuZCBOIHZhbHVlcyAqLwogCWJ1ZlswXSA9IDB4NDQ7CkBAIC02NzQsNyAr Njc5LDcgQEAgdGRhOTk4eF9jb25maWd1cmVfYXVkaW8oc3RydWN0IHRkYTk5OHhfcHJpdiAqcHJp diwKIAl0ZGE5OTh4X2F1ZGlvX211dGUocHJpdiwgZmFsc2UpOwogCiAJLyogV3JpdGUgdGhlIGF1 ZGlvIGluZm9ybWF0aW9uIHBhY2tldCAqLwotCXRkYTk5OHhfd3JpdGVfYWlmKHByaXYsIHApOwor CXRkYTk5OHhfd3JpdGVfYWlmKHByaXYpOwogfQogCiAvKiBEUk0gZW5jb2RlciBmdW5jdGlvbnMg Ki8KQEAgLTY5OCw3ICs3MDMsMTMgQEAgdGRhOTk4eF9lbmNvZGVyX3NldF9jb25maWcoc3RydWN0 IGRybV9lbmNvZGVyICplbmNvZGVyLCB2b2lkICpwYXJhbXMpCiAJCQkgICAgVklQX0NOVFJMXzJf U1dBUF9GKHAtPnN3YXBfZikgfAogCQkJICAgIChwLT5taXJyX2YgPyBWSVBfQ05UUkxfMl9NSVJS X0YgOiAwKTsKIAotCXByaXYtPnBhcmFtcyA9ICpwOworCW1lbWNweShwcml2LT5hdWRpb19mcmFt ZSwgcC0+YXVkaW9fZnJhbWUsCisJCQlzaXplb2YgcHJpdi0+YXVkaW9fZnJhbWUpOworCisJaWYg KHAtPmF1ZGlvX2NmZykgeworCQlwcml2LT5hdWRpb19wb3J0ID0gcC0+YXVkaW9fY2ZnOworCQlw cml2LT5hdWRpb190eXBlID0gcC0+YXVkaW9fZm9ybWF0OworCX0KIH0KIAogc3RhdGljIHZvaWQK QEAgLTk0Nyw4ICs5NTgsOCBAQCB0ZGE5OTh4X2VuY29kZXJfbW9kZV9zZXQoc3RydWN0IGRybV9l bmNvZGVyICplbmNvZGVyLAogCiAJCXRkYTk5OHhfd3JpdGVfYXZpKHByaXYsIG1vZGUpOwogCi0J CWlmIChwcml2LT5wYXJhbXMuYXVkaW9fY2ZnKQotCQkJdGRhOTk4eF9jb25maWd1cmVfYXVkaW8o cHJpdiwgbW9kZSwgJnByaXYtPnBhcmFtcyk7CisJCWlmIChwcml2LT5hdWRpb190eXBlKQorCQkJ dGRhOTk4eF9jb25maWd1cmVfYXVkaW8ocHJpdiwgbW9kZSk7CiAJfQogfQogCkBAIC0xMTU3LDYg KzExNjgsOCBAQCB0ZGE5OTh4X2VuY29kZXJfaW5pdChzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50 LAogCQkgICAgc3RydWN0IGRybV9lbmNvZGVyX3NsYXZlICplbmNvZGVyX3NsYXZlKQogewogCXN0 cnVjdCB0ZGE5OTh4X3ByaXYgKnByaXY7CisJc3RydWN0IGRldmljZV9ub2RlICpucCA9IGNsaWVu dC0+ZGV2Lm9mX25vZGU7CisJdTMyIHZpZGVvOwogCWludCByZXQ7CiAKIAlwcml2ID0ga3phbGxv YyhzaXplb2YoKnByaXYpLCBHRlBfS0VSTkVMKTsKQEAgLTExNjYsNiArMTE3OSw3IEBAIHRkYTk5 OHhfZW5jb2Rlcl9pbml0KHN0cnVjdCBpMmNfY2xpZW50ICpjbGllbnQsCiAJcHJpdi0+dmlwX2Nu dHJsXzAgPSBWSVBfQ05UUkxfMF9TV0FQX0EoMikgfCBWSVBfQ05UUkxfMF9TV0FQX0IoMyk7CiAJ cHJpdi0+dmlwX2NudHJsXzEgPSBWSVBfQ05UUkxfMV9TV0FQX0MoMCkgfCBWSVBfQ05UUkxfMV9T V0FQX0QoMSk7CiAJcHJpdi0+dmlwX2NudHJsXzIgPSBWSVBfQ05UUkxfMl9TV0FQX0UoNCkgfCBW SVBfQ05UUkxfMl9TV0FQX0YoNSk7CisJcHJpdi0+YXVkaW9fZnJhbWVbMV0gPSAxOwkJLyogY2hh bm5lbHMgLSAxICovCiAKIAlwcml2LT5jdXJyZW50X3BhZ2UgPSAweGZmOwogCXByaXYtPmhkbWkg PSBjbGllbnQ7CkBAIC0xMjI1LDYgKzEyMzksMTcgQEAgdGRhOTk4eF9lbmNvZGVyX2luaXQoc3Ry dWN0IGkyY19jbGllbnQgKmNsaWVudCwKIAljZWNfd3JpdGUocHJpdiwgUkVHX0NFQ19GUk9fSU1f Q0xLX0NUUkwsCiAJCQlDRUNfRlJPX0lNX0NMS19DVFJMX0dIT1NUX0RJUyB8IENFQ19GUk9fSU1f Q0xLX0NUUkxfSU1DTEtfU0VMKTsKIAorCWlmICghbnApCisJCXJldHVybiAwOwkJLyogbm9uLURU ICovCisKKwkvKiBnZXQgdGhlIG9wdGlvbmFsIHZpZGVvIHByb3BlcnRpZXMgKi8KKwlyZXQgPSBv Zl9wcm9wZXJ0eV9yZWFkX3UzMihucCwgInZpZGVvLXBvcnRzIiwgJnZpZGVvKTsKKwlpZiAocmV0 ID09IDApIHsKKwkJcHJpdi0+dmlwX2NudHJsXzAgPSB2aWRlbyA+PiAxNjsKKwkJcHJpdi0+dmlw X2NudHJsXzEgPSB2aWRlbyA+PiA4OworCQlwcml2LT52aXBfY250cmxfMiA9IHZpZGVvOworCX0K KwogCXJldHVybiAwOwogCiBmYWlsOgpAQCAtMTIzOSw2ICsxMjY0LDE0IEBAIGZhaWw6CiAJcmV0 dXJuIC1FTlhJTzsKIH0KIAorI2lmZGVmIENPTkZJR19PRgorc3RhdGljIGNvbnN0IHN0cnVjdCBv Zl9kZXZpY2VfaWQgdGRhOTk4eF9kdF9pZHNbXSA9IHsKKwl7IC5jb21wYXRpYmxlID0gIm54cCx0 ZGE5OTh4IiwgfSwKKwl7IH0KK307CitNT0RVTEVfREVWSUNFX1RBQkxFKG9mLCB0ZGE5OTh4X2R0 X2lkcyk7CisjZW5kaWYKKwogc3RhdGljIHN0cnVjdCBpMmNfZGV2aWNlX2lkIHRkYTk5OHhfaWRz W10gPSB7CiAJeyAidGRhOTk4eCIsIDAgfSwKIAl7IH0KQEAgLTEyNTEsNiArMTI4NCw3IEBAIHN0 YXRpYyBzdHJ1Y3QgZHJtX2kyY19lbmNvZGVyX2RyaXZlciB0ZGE5OTh4X2RyaXZlciA9IHsKIAkJ LnJlbW92ZSA9IHRkYTk5OHhfcmVtb3ZlLAogCQkuZHJpdmVyID0gewogCQkJLm5hbWUgPSAidGRh OTk4eCIsCisJCQkub2ZfbWF0Y2hfdGFibGUgPSBvZl9tYXRjaF9wdHIodGRhOTk4eF9kdF9pZHMp LAogCQl9LAogCQkuaWRfdGFibGUgPSB0ZGE5OTh4X2lkcywKIAl9LAotLSAKS2VuIGFyIGMnaGVu dGHDsQl8CSAgICAgICoqIEJyZWl6aCBoYSBMaW51eCBhdGF2ISAqKgpKZWYJCXwJCWh0dHA6Ly9t b2luZWpmLmZyZWUuZnIvCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fCmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNrdG9w Lm9yZwpodHRwOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vZHJpLWRl dmVsCg== From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755458AbaAILLJ (ORCPT ); Thu, 9 Jan 2014 06:11:09 -0500 Received: from smtp1-g21.free.fr ([212.27.42.1]:34502 "EHLO smtp1-g21.free.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751988AbaAILK4 convert rfc822-to-8bit (ORCPT ); Thu, 9 Jan 2014 06:10:56 -0500 Date: Thu, 9 Jan 2014 12:03:24 +0100 From: Jean-Francois Moine To: dri-devel@lists.freedesktop.org Cc: Dave Airlie , Rob Clark , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v2 12/28] drm/i2c: tda998x: add DT support Message-ID: <20140109120324.4e2c8aca@armhf> X-Mailer: Claws Mail 3.9.3 (GTK+ 2.24.22; arm-unknown-linux-gnueabihf) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch adds DT support to the tda998x. As a side effect, now, the audio sample rate is always 48kHz and the audio clock is always set. Signed-off-by: Jean-Francois Moine --- .../devicetree/bindings/drm/i2c/tda998x.txt | 16 ++++++ drivers/gpu/drm/i2c/tda998x_drv.c | 66 ++++++++++++++++------ 2 file changed, 66 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/drm/i2c/tda998x.txt b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt new file mode 100644 index 0000000..f07339e1 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt @@ -0,0 +1,16 @@ +Device-Tree bindings for the NXP TDA998x HDMI transmitter + +Required properties; + - compatible: must be "nxp,tda998x" + +Optional properties: + - video-ports: 24 bits value - default: <0x230145> + +Example: + + tda998x: hdmi-encoder { + compatible = "nxp,tda998x"; + reg = <0x70>; + pinctrl-0 = <&pmx_camera>; + pinctrl-names = "default"; + }; diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 2ba0355..b87802f 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -28,17 +28,22 @@ #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) +#define AUDIO_SAMPLE 48 /* 48 kHz */ + struct tda998x_priv { struct i2c_client *cec; struct i2c_client *hdmi; uint16_t rev; uint8_t current_page; - int dpms; + u8 dpms; bool is_hdmi_sink; u8 vip_cntrl_0; u8 vip_cntrl_1; u8 vip_cntrl_2; - struct tda998x_encoder_params params; + + u8 audio_type; /* audio type */ + u8 audio_frame[6]; + u32 audio_port; }; #define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv) @@ -539,7 +544,7 @@ tda998x_write_if(struct tda998x_priv *priv, uint8_t bit, uint16_t addr, } static void -tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p) +tda998x_write_aif(struct tda998x_priv *priv) { u8 buf[PB(HDMI_AUDIO_INFOFRAME_SIZE) + 1]; @@ -547,10 +552,10 @@ tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p) buf[HB(0)] = HDMI_INFOFRAME_TYPE_AUDIO; buf[HB(1)] = 0x01; buf[HB(2)] = HDMI_AUDIO_INFOFRAME_SIZE; - buf[PB(1)] = p->audio_frame[1] & 0x07; /* CC */ - buf[PB(2)] = p->audio_frame[2] & 0x1c; /* SF */ - buf[PB(4)] = p->audio_frame[4]; - buf[PB(5)] = p->audio_frame[5] & 0xf8; /* DM_INH + LSV */ + buf[PB(1)] = priv->audio_frame[1] & 0x07; /* CC */ + buf[PB(2)] = priv->audio_frame[2] & 0x1c; /* SF */ + buf[PB(4)] = priv->audio_frame[4]; + buf[PB(5)] = priv->audio_frame[5] & 0xf8; /* DM_INH + LSV */ tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf, sizeof(buf)); @@ -586,17 +591,17 @@ static void tda998x_audio_mute(struct tda998x_priv *priv, bool on) static void tda998x_configure_audio(struct tda998x_priv *priv, - struct drm_display_mode *mode, struct tda998x_encoder_params *p) + struct drm_display_mode *mode) { uint8_t buf[6], clksel_aip, clksel_fs, ca_i2s, cts_n, adiv; uint32_t n; /* Enable audio ports */ - reg_write(priv, REG_ENA_AP, p->audio_cfg); - reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg); + reg_write(priv, REG_ENA_AP, priv->audio_port); + reg_write(priv, REG_ENA_ACLK, 0x01); /* enable clock */ /* Set audio input source */ - switch (p->audio_format) { + switch (priv->audio_type) { case AFMT_SPDIF: reg_write(priv, REG_MUX_AP, 0x40); clksel_aip = AIP_CLKSEL_AIP(0); @@ -644,7 +649,7 @@ tda998x_configure_audio(struct tda998x_priv *priv, * This is the approximate value of N, which happens to be * the recommended values for non-coherent clocks. */ - n = 128 * p->audio_sample_rate / 1000; + n = 128 * AUDIO_SAMPLE; /* acr_n = 128 * sample_rate / 1000 */ /* Write the CTS and N values */ buf[0] = 0x44; @@ -674,7 +679,7 @@ tda998x_configure_audio(struct tda998x_priv *priv, tda998x_audio_mute(priv, false); /* Write the audio information packet */ - tda998x_write_aif(priv, p); + tda998x_write_aif(priv); } /* DRM encoder functions */ @@ -698,7 +703,13 @@ tda998x_encoder_set_config(struct drm_encoder *encoder, void *params) VIP_CNTRL_2_SWAP_F(p->swap_f) | (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0); - priv->params = *p; + memcpy(priv->audio_frame, p->audio_frame, + sizeof priv->audio_frame); + + if (p->audio_cfg) { + priv->audio_port = p->audio_cfg; + priv->audio_type = p->audio_format; + } } static void @@ -947,8 +958,8 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, tda998x_write_avi(priv, mode); - if (priv->params.audio_cfg) - tda998x_configure_audio(priv, mode, &priv->params); + if (priv->audio_type) + tda998x_configure_audio(priv, mode); } } @@ -1157,6 +1168,8 @@ tda998x_encoder_init(struct i2c_client *client, struct drm_encoder_slave *encoder_slave) { struct tda998x_priv *priv; + struct device_node *np = client->dev.of_node; + u32 video; int ret; priv = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -1166,6 +1179,7 @@ tda998x_encoder_init(struct i2c_client *client, priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3); priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1); priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5); + priv->audio_frame[1] = 1; /* channels - 1 */ priv->current_page = 0xff; priv->hdmi = client; @@ -1225,6 +1239,17 @@ tda998x_encoder_init(struct i2c_client *client, cec_write(priv, REG_CEC_FRO_IM_CLK_CTRL, CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL); + if (!np) + return 0; /* non-DT */ + + /* get the optional video properties */ + ret = of_property_read_u32(np, "video-ports", &video); + if (ret == 0) { + priv->vip_cntrl_0 = video >> 16; + priv->vip_cntrl_1 = video >> 8; + priv->vip_cntrl_2 = video; + } + return 0; fail: @@ -1239,6 +1264,14 @@ fail: return -ENXIO; } +#ifdef CONFIG_OF +static const struct of_device_id tda998x_dt_ids[] = { + { .compatible = "nxp,tda998x", }, + { } +}; +MODULE_DEVICE_TABLE(of, tda998x_dt_ids); +#endif + static struct i2c_device_id tda998x_ids[] = { { "tda998x", 0 }, { } @@ -1251,6 +1284,7 @@ static struct drm_i2c_encoder_driver tda998x_driver = { .remove = tda998x_remove, .driver = { .name = "tda998x", + .of_match_table = of_match_ptr(tda998x_dt_ids), }, .id_table = tda998x_ids, }, -- Ken ar c'hentaƱ | ** Breizh ha Linux atav! ** Jef | http://moinejf.free.fr/