From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jean-Francois Moine Subject: [PATCH v2 28/28] drm/i2c: tda998x: add a CODEC interface Date: Thu, 9 Jan 2014 12:08:03 +0100 Message-ID: <20140109120803.6c26b401@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: alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org List-Id: alsa-devel@alsa-project.org VGhlIFREQTk5OHggY2hpcHMgbWF5IGdldCBhdWRpbyBpbnB1dCBmcm9tIEkyUyBvciBTL1BESUYg YW5kIHRoaXMgaW5wdXQKaXMgZGVmaW5lZCBieSB0aGUgYXVkaW8gc3Vic3lzdGVtLgoKSW4gdGhl IG90aGVyIHdheSwgdGhlIGF1ZGlvIHN1YnN5c3RlbSBtYXkgbmVlZCB0byBrbm93IGlmIGF1ZGlv IG91dHB1dAptYXkgYmUgZG9uZSB0aHJvdWdoIHRoZSBIRE1JIGNvbm5lY3Rvci4KClRoaXMgcGF0 Y2ggYWRkcyBhIENPREVDIGludGVyZmFjZSBmb3IgZXhjaGFuZ2VzIGJldHdlZW4gdGhlIEhETUkg dHJhbnNtaXR0ZXIgYW5kIHRoZSBhdWRpbyBzdWJzeXN0ZW0uCgpTaWduZWQtb2ZmLWJ5OiBKZWFu LUZyYW5jb2lzIE1vaW5lIDxtb2luZWpmQGZyZWUuZnI+Ci0tLQogZHJpdmVycy9ncHUvZHJtL2ky Yy90ZGE5OTh4X2Rydi5jICB8IDcwICsrKysrKysrKysrKysrKysrKysrLS0KIDEgZmlsZSBjaGFu Z2VkLCA2NSBpbnNlcnRpb25zKCspLCA1IGRlbGV0aW9ucygtKQoKZGlmZiAtLWdpdCBhL2RyaXZl cnMvZ3B1L2RybS9pMmMvdGRhOTk4eF9kcnYuYyBiL2RyaXZlcnMvZ3B1L2RybS9pMmMvdGRhOTk4 eF9kcnYuYwppbmRleCA2N2Q3NDUwLi41YTE4NmU0IDEwMDY0NAotLS0gYS9kcml2ZXJzL2dwdS9k cm0vaTJjL3RkYTk5OHhfZHJ2LmMKKysrIGIvZHJpdmVycy9ncHUvZHJtL2kyYy90ZGE5OTh4X2Ry di5jCkBAIC00Miw3ICs0Miw4IEBAIHN0cnVjdCB0ZGE5OTh4X3ByaXYgewogCXU4IHZpcF9jbnRy bF8xOwogCXU4IHZpcF9jbnRybF8yOwogCi0JdTggYXVkaW9fdHlwZTsJCS8qIGF1ZGlvIHR5cGUg Ki8KKwl1OCBhdWRpb190eXBlOwkJLyogYXVkaW8gdHlwZSBhbmQgJ2FjdGl2ZScgZmxhZyAqLwor I2RlZmluZSBBVURJT19BQ1RJVkUgMHg4MAogCXU4IGF1ZGlvX2ZyYW1lWzZdOwogCXUzMiBhdWRp b19wb3J0OwogCkBAIC01MCw2ICs1MSw5IEBAIHN0cnVjdCB0ZGE5OTh4X3ByaXYgewogCXdhaXRf cXVldWVfaGVhZF90IHdxX2VkaWQ7CiAJdm9sYXRpbGUgaW50IHdxX2VkaWRfd2FpdDsKIAlzdHJ1 Y3QgZHJtX2VuY29kZXIgKmVuY29kZXI7CisKKwlzdHJ1Y3Qgc25kX3NvY19jb2RlYyAqY29kZWM7 CisJdm9pZCAoKmV2ZW50KShzdHJ1Y3Qgc25kX3NvY19jb2RlYyAqY29kZWMsIGludCBhY3RpdmF0 ZSk7CiB9OwogCiAjZGVmaW5lIHRvX3RkYTk5OHhfcHJpdih4KSAgKChzdHJ1Y3QgdGRhOTk4eF9w cml2ICopdG9fZW5jb2Rlcl9zbGF2ZSh4KS0+c2xhdmVfcHJpdikKQEAgLTczMSwxNCArNzM1LDE0 IEBAIHRkYTk5OHhfY29uZmlndXJlX2F1ZGlvKHN0cnVjdCB0ZGE5OTh4X3ByaXYgKnByaXYsCiAK IAkvKiBTZXQgYXVkaW8gaW5wdXQgc291cmNlICovCiAJc3dpdGNoIChwcml2LT5hdWRpb190eXBl KSB7Ci0JY2FzZSBBRk1UX1NQRElGOgorCWNhc2UgQUZNVF9TUERJRiB8IEFVRElPX0FDVElWRToK IAkJcmVnX3dyaXRlKHByaXYsIFJFR19NVVhfQVAsIE1VWF9BUF9TRUxFQ1RfU1BESUYpOwogCQlj bGtzZWxfYWlwID0gQUlQX0NMS1NFTF9BSVAoU0VMX0FJUF9TUERJRik7CiAJCWNsa3NlbF9mcyA9 IEFJUF9DTEtTRUxfRlMoQ1RTUkVGX0ZTNjRTUERJRik7CiAJCWN0c19uID0gQ1RTX05fTSgzKSB8 IENUU19OX0soMyk7CiAJCWJyZWFrOwogCi0JY2FzZSBBRk1UX0kyUzoKKwljYXNlIEFGTVRfSTJT IHwgQVVESU9fQUNUSVZFOgogCQlyZWdfd3JpdGUocHJpdiwgUkVHX01VWF9BUCwgTVVYX0FQX1NF TEVDVF9JMlMpOwogCQljbGtzZWxfYWlwID0gQUlQX0NMS1NFTF9BSVAoU0VMX0FJUF9JMlMpOwog CQljbGtzZWxfZnMgPSBBSVBfQ0xLU0VMX0ZTKENUU1JFRl9BQ0xLKTsKQEAgLTgxMyw2ICs4MTcs NTggQEAgdGRhOTk4eF9jb25maWd1cmVfYXVkaW8oc3RydWN0IHRkYTk5OHhfcHJpdiAqcHJpdiwK IAl0ZGE5OTh4X3dyaXRlX2FpZihwcml2KTsKIH0KIAorLyogdGRhOTk4eCBjb2RlYyBpbnRlcmZh Y2UgKi8KK3ZvaWQgdGRhOTk4eF9hdWRpb19yZWdpc3RlcihzdHJ1Y3QgaTJjX2NsaWVudCAqY2xp ZW50LAorCQkJc3RydWN0IHNuZF9zb2NfY29kZWMgKmNvZGVjLAorCQkJdm9pZCAoKmV2ZW50KShz dHJ1Y3Qgc25kX3NvY19jb2RlYyAqY29kZWMsIGludCBhY3RpdmF0ZSkpCit7CisJc3RydWN0IHRk YTk5OHhfcHJpdiAqcHJpdiA9IGkyY19nZXRfY2xpZW50ZGF0YShjbGllbnQpOworCisJLyogbWVt b3JpemUgdGhlIGNvZGVjIGFuZCB0aGUgY2FsbGJhY2sgZnVuY3Rpb24gKi8KKwlwcml2LT5jb2Rl YyA9IGNvZGVjOworCXByaXYtPmV2ZW50ID0gZXZlbnQ7Cit9CitFWFBPUlRfU1lNQk9MX0dQTCh0 ZGE5OTh4X2F1ZGlvX3JlZ2lzdGVyKTsKKwordm9pZCB0ZGE5OTh4X2F1ZGlvX3VwZGF0ZShzdHJ1 Y3QgaTJjX2NsaWVudCAqY2xpZW50LAorCQkJaW50IHR5cGUsCisJCQl1MzIgcG9ydCkKK3sKKwlz dHJ1Y3QgdGRhOTk4eF9wcml2ICpwcml2ID0gaTJjX2dldF9jbGllbnRkYXRhKGNsaWVudCk7CisK KwkvKiBpZiB0aGUgYXVkaW8gb3V0cHV0IGlzIGFjdGl2ZSwgaXQgbWF5IGJlIGEgc2Vjb25kIHN0 YXJ0IG9yIGEgc3RvcCAqLworCWlmICh0eXBlID09IDAgfHwgKHByaXYtPmF1ZGlvX3R5cGUgJiBB VURJT19BQ1RJVkUpKSB7CisJCWlmICh0eXBlID09IDApIHsKKwkJCXByaXYtPmF1ZGlvX3R5cGUg Jj0gfkFVRElPX0FDVElWRTsJLyogc3RvcCAqLworCQkJcmVnX3dyaXRlKHByaXYsIFJFR19FTkFf QVAsIDApOworCQl9CisJCXJldHVybjsKKwl9CisKKwlwcml2LT5hdWRpb19wb3J0ID0gcG9ydDsK KworCS8qIGRvbid0IHJlc3RhcnQgYXVkaW8gaWYgc2FtZSBpbnB1dCB0eXBlICovCisJaWYgKHR5 cGUgPT0gcHJpdi0+YXVkaW9fdHlwZSkgeworCQlwcml2LT5hdWRpb190eXBlIHw9IEFVRElPX0FD VElWRTsKKwkJcmVnX3dyaXRlKHByaXYsIFJFR19FTkFfQVAsIHByaXYtPmF1ZGlvX3BvcnQpOwor CQlyZXR1cm47CisJfQorCisJcHJpdi0+YXVkaW9fdHlwZSA9IHR5cGUgfCBBVURJT19BQ1RJVkU7 CisKKwl0ZGE5OTh4X2NvbmZpZ3VyZV9hdWRpbyhwcml2LCAmcHJpdi0+ZW5jb2Rlci0+Y3J0Yy0+ aHdtb2RlKTsKK30KK0VYUE9SVF9TWU1CT0xfR1BMKHRkYTk5OHhfYXVkaW9fdXBkYXRlKTsKKwor Lyogc2VuZCBhbiBhdWRpbyBldmVudCB0byB0aGUgdGRhIGNvZGVjICovCitzdGF0aWMgdm9pZCBz ZW5kX2F1ZGlvX2V2ZW50KHN0cnVjdCB0ZGE5OTh4X3ByaXYgKnByaXYsCisJCQkJaW50IGV2ZW50 KQoreworCWlmICghcHJpdi0+ZXZlbnQpCisJCXJldHVybjsKKwlwcml2LT5ldmVudChwcml2LT5j b2RlYywgZXZlbnQpOworfQorCiAvKiBEUk0gZW5jb2RlciBmdW5jdGlvbnMgKi8KIAogLyogdGhp cyBmdW5jdGlvbiBpcyBub3QgY2FsbGVkIHdoZW4gbm8gaW5mby0+cGxhdGZvcm0gKERUIHN1cHBv cnQpICovCkBAIC04NDAsNyArODk2LDcgQEAgdGRhOTk4eF9lbmNvZGVyX3NldF9jb25maWcoc3Ry dWN0IGRybV9lbmNvZGVyICplbmNvZGVyLCB2b2lkICpwYXJhbXMpCiAKIAlpZiAocC0+YXVkaW9f Y2ZnKSB7CiAJCXByaXYtPmF1ZGlvX3BvcnQgPSBwLT5hdWRpb19jZmc7Ci0JCXByaXYtPmF1ZGlv X3R5cGUgPSBwLT5hdWRpb19mb3JtYXQ7CisJCXByaXYtPmF1ZGlvX3R5cGUgPSBwLT5hdWRpb19m b3JtYXQgfCBBVURJT19BQ1RJVkU7CiAJfQogfQogCkBAIC0xMTA1LDkgKzExNjEsMTAgQEAgdGRh OTk4eF9lbmNvZGVyX21vZGVfc2V0KHN0cnVjdCBkcm1fZW5jb2RlciAqZW5jb2RlciwKIAogCQl0 ZGE5OTh4X3dyaXRlX2F2aShwcml2LCBtb2RlKTsKIAotCQlpZiAocHJpdi0+YXVkaW9fdHlwZSkK KwkJaWYgKHByaXYtPmF1ZGlvX3R5cGUgJiBBVURJT19BQ1RJVkUpCiAJCQl0ZGE5OTh4X2NvbmZp Z3VyZV9hdWRpbyhwcml2LCBtb2RlKTsKIAl9CisJc2VuZF9hdWRpb19ldmVudChwcml2LCBwcml2 LT5pc19oZG1pX3NpbmspOwogCiAJLyogbXVzdCBiZSBsYXN0IHJlZ2lzdGVyIHNldDogKi8KIAly ZWdfd3JpdGUocHJpdiwgUkVHX1RCR19DTlRSTF8wLCAwKTsKQEAgLTEyNjMsNiArMTMyMCw3IEBA IHRkYTk5OHhfZW5jb2Rlcl9nZXRfbW9kZXMoc3RydWN0IGRybV9lbmNvZGVyICplbmNvZGVyLAog CQlkcm1fbW9kZV9jb25uZWN0b3JfdXBkYXRlX2VkaWRfcHJvcGVydHkoY29ubmVjdG9yLCBlZGlk KTsKIAkJbiA9IGRybV9hZGRfZWRpZF9tb2Rlcyhjb25uZWN0b3IsIGVkaWQpOwogCQlwcml2LT5p c19oZG1pX3NpbmsgPSBkcm1fZGV0ZWN0X2hkbWlfbW9uaXRvcihlZGlkKTsKKwkJc2VuZF9hdWRp b19ldmVudChwcml2LCBwcml2LT5pc19oZG1pX3NpbmspOwogCQlrZnJlZShlZGlkKTsKIAl9CiAK QEAgLTEzNDksNiArMTQwNyw4IEBAIHRkYTk5OHhfZW5jb2Rlcl9pbml0KHN0cnVjdCBpMmNfY2xp ZW50ICpjbGllbnQsCiAJaWYgKCFwcml2KQogCQlyZXR1cm4gLUVOT01FTTsKIAorCWkyY19zZXRf Y2xpZW50ZGF0YShjbGllbnQsIHByaXYpOworCiAJcHJpdi0+dmlwX2NudHJsXzAgPSBWSVBfQ05U UkxfMF9TV0FQX0EoMikgfCBWSVBfQ05UUkxfMF9TV0FQX0IoMyk7CiAJcHJpdi0+dmlwX2NudHJs XzEgPSBWSVBfQ05UUkxfMV9TV0FQX0MoMCkgfCBWSVBfQ05UUkxfMV9TV0FQX0QoMSk7CiAJcHJp di0+dmlwX2NudHJsXzIgPSBWSVBfQ05UUkxfMl9TV0FQX0UoNCkgfCBWSVBfQ05UUkxfMl9TV0FQ X0YoNSk7Ci0tIApLZW4gYXIgYydoZW50YcOxCXwJICAgICAgKiogQnJlaXpoIGhhIExpbnV4IGF0 YXYhICoqCkplZgkJfAkJaHR0cDovL21vaW5lamYuZnJlZS5mci8KX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX18KZHJpLWRldmVsIG1haWxpbmcgbGlzdApkcmkt ZGV2ZWxAbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHA6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcv bWFpbG1hbi9saXN0aW5mby9kcmktZGV2ZWwK From mboxrd@z Thu Jan 1 00:00:00 1970 From: moinejf@free.fr (Jean-Francois Moine) Date: Thu, 9 Jan 2014 12:08:03 +0100 Subject: [PATCH v2 28/28] drm/i2c: tda998x: add a CODEC interface Message-ID: <20140109120803.6c26b401@armhf> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org The TDA998x chips may get audio input from I2S or S/PDIF and this input is defined by the audio subsystem. In the other way, the audio subsystem may need to know if audio output may be done through the HDMI connector. This patch adds a CODEC interface for exchanges between the HDMI transmitter and the audio subsystem. Signed-off-by: Jean-Francois Moine --- drivers/gpu/drm/i2c/tda998x_drv.c | 70 ++++++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 67d7450..5a186e4 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -42,7 +42,8 @@ struct tda998x_priv { u8 vip_cntrl_1; u8 vip_cntrl_2; - u8 audio_type; /* audio type */ + u8 audio_type; /* audio type and 'active' flag */ +#define AUDIO_ACTIVE 0x80 u8 audio_frame[6]; u32 audio_port; @@ -50,6 +51,9 @@ struct tda998x_priv { wait_queue_head_t wq_edid; volatile int wq_edid_wait; struct drm_encoder *encoder; + + struct snd_soc_codec *codec; + void (*event)(struct snd_soc_codec *codec, int activate); }; #define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv) @@ -731,14 +735,14 @@ tda998x_configure_audio(struct tda998x_priv *priv, /* Set audio input source */ switch (priv->audio_type) { - case AFMT_SPDIF: + case AFMT_SPDIF | AUDIO_ACTIVE: reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF); clksel_aip = AIP_CLKSEL_AIP(SEL_AIP_SPDIF); clksel_fs = AIP_CLKSEL_FS(CTSREF_FS64SPDIF); cts_n = CTS_N_M(3) | CTS_N_K(3); break; - case AFMT_I2S: + case AFMT_I2S | AUDIO_ACTIVE: reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S); clksel_aip = AIP_CLKSEL_AIP(SEL_AIP_I2S); clksel_fs = AIP_CLKSEL_FS(CTSREF_ACLK); @@ -813,6 +817,58 @@ tda998x_configure_audio(struct tda998x_priv *priv, tda998x_write_aif(priv); } +/* tda998x codec interface */ +void tda998x_audio_register(struct i2c_client *client, + struct snd_soc_codec *codec, + void (*event)(struct snd_soc_codec *codec, int activate)) +{ + struct tda998x_priv *priv = i2c_get_clientdata(client); + + /* memorize the codec and the callback function */ + priv->codec = codec; + priv->event = event; +} +EXPORT_SYMBOL_GPL(tda998x_audio_register); + +void tda998x_audio_update(struct i2c_client *client, + int type, + u32 port) +{ + struct tda998x_priv *priv = i2c_get_clientdata(client); + + /* if the audio output is active, it may be a second start or a stop */ + if (type == 0 || (priv->audio_type & AUDIO_ACTIVE)) { + if (type == 0) { + priv->audio_type &= ~AUDIO_ACTIVE; /* stop */ + reg_write(priv, REG_ENA_AP, 0); + } + return; + } + + priv->audio_port = port; + + /* don't restart audio if same input type */ + if (type == priv->audio_type) { + priv->audio_type |= AUDIO_ACTIVE; + reg_write(priv, REG_ENA_AP, priv->audio_port); + return; + } + + priv->audio_type = type | AUDIO_ACTIVE; + + tda998x_configure_audio(priv, &priv->encoder->crtc->hwmode); +} +EXPORT_SYMBOL_GPL(tda998x_audio_update); + +/* send an audio event to the tda codec */ +static void send_audio_event(struct tda998x_priv *priv, + int event) +{ + if (!priv->event) + return; + priv->event(priv->codec, event); +} + /* DRM encoder functions */ /* this function is not called when no info->platform (DT support) */ @@ -840,7 +896,7 @@ tda998x_encoder_set_config(struct drm_encoder *encoder, void *params) if (p->audio_cfg) { priv->audio_port = p->audio_cfg; - priv->audio_type = p->audio_format; + priv->audio_type = p->audio_format | AUDIO_ACTIVE; } } @@ -1105,9 +1161,10 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, tda998x_write_avi(priv, mode); - if (priv->audio_type) + if (priv->audio_type & AUDIO_ACTIVE) tda998x_configure_audio(priv, mode); } + send_audio_event(priv, priv->is_hdmi_sink); /* must be last register set: */ reg_write(priv, REG_TBG_CNTRL_0, 0); @@ -1263,6 +1320,7 @@ tda998x_encoder_get_modes(struct drm_encoder *encoder, drm_mode_connector_update_edid_property(connector, edid); n = drm_add_edid_modes(connector, edid); priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid); + send_audio_event(priv, priv->is_hdmi_sink); kfree(edid); } @@ -1349,6 +1407,8 @@ tda998x_encoder_init(struct i2c_client *client, if (!priv) return -ENOMEM; + i2c_set_clientdata(client, priv); + 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); -- Ken ar c'henta? | ** Breizh ha Linux atav! ** Jef | http://moinejf.free.fr/ From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753706AbaAILOC (ORCPT ); Thu, 9 Jan 2014 06:14:02 -0500 Received: from smtp1-g21.free.fr ([212.27.42.1]:44326 "EHLO smtp1-g21.free.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755821AbaAILNc convert rfc822-to-8bit (ORCPT ); Thu, 9 Jan 2014 06:13:32 -0500 Date: Thu, 9 Jan 2014 12:08:03 +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, alsa-devel@alsa-project.org Subject: [PATCH v2 28/28] drm/i2c: tda998x: add a CODEC interface Message-ID: <20140109120803.6c26b401@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 The TDA998x chips may get audio input from I2S or S/PDIF and this input is defined by the audio subsystem. In the other way, the audio subsystem may need to know if audio output may be done through the HDMI connector. This patch adds a CODEC interface for exchanges between the HDMI transmitter and the audio subsystem. Signed-off-by: Jean-Francois Moine --- drivers/gpu/drm/i2c/tda998x_drv.c | 70 ++++++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 67d7450..5a186e4 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -42,7 +42,8 @@ struct tda998x_priv { u8 vip_cntrl_1; u8 vip_cntrl_2; - u8 audio_type; /* audio type */ + u8 audio_type; /* audio type and 'active' flag */ +#define AUDIO_ACTIVE 0x80 u8 audio_frame[6]; u32 audio_port; @@ -50,6 +51,9 @@ struct tda998x_priv { wait_queue_head_t wq_edid; volatile int wq_edid_wait; struct drm_encoder *encoder; + + struct snd_soc_codec *codec; + void (*event)(struct snd_soc_codec *codec, int activate); }; #define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv) @@ -731,14 +735,14 @@ tda998x_configure_audio(struct tda998x_priv *priv, /* Set audio input source */ switch (priv->audio_type) { - case AFMT_SPDIF: + case AFMT_SPDIF | AUDIO_ACTIVE: reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF); clksel_aip = AIP_CLKSEL_AIP(SEL_AIP_SPDIF); clksel_fs = AIP_CLKSEL_FS(CTSREF_FS64SPDIF); cts_n = CTS_N_M(3) | CTS_N_K(3); break; - case AFMT_I2S: + case AFMT_I2S | AUDIO_ACTIVE: reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S); clksel_aip = AIP_CLKSEL_AIP(SEL_AIP_I2S); clksel_fs = AIP_CLKSEL_FS(CTSREF_ACLK); @@ -813,6 +817,58 @@ tda998x_configure_audio(struct tda998x_priv *priv, tda998x_write_aif(priv); } +/* tda998x codec interface */ +void tda998x_audio_register(struct i2c_client *client, + struct snd_soc_codec *codec, + void (*event)(struct snd_soc_codec *codec, int activate)) +{ + struct tda998x_priv *priv = i2c_get_clientdata(client); + + /* memorize the codec and the callback function */ + priv->codec = codec; + priv->event = event; +} +EXPORT_SYMBOL_GPL(tda998x_audio_register); + +void tda998x_audio_update(struct i2c_client *client, + int type, + u32 port) +{ + struct tda998x_priv *priv = i2c_get_clientdata(client); + + /* if the audio output is active, it may be a second start or a stop */ + if (type == 0 || (priv->audio_type & AUDIO_ACTIVE)) { + if (type == 0) { + priv->audio_type &= ~AUDIO_ACTIVE; /* stop */ + reg_write(priv, REG_ENA_AP, 0); + } + return; + } + + priv->audio_port = port; + + /* don't restart audio if same input type */ + if (type == priv->audio_type) { + priv->audio_type |= AUDIO_ACTIVE; + reg_write(priv, REG_ENA_AP, priv->audio_port); + return; + } + + priv->audio_type = type | AUDIO_ACTIVE; + + tda998x_configure_audio(priv, &priv->encoder->crtc->hwmode); +} +EXPORT_SYMBOL_GPL(tda998x_audio_update); + +/* send an audio event to the tda codec */ +static void send_audio_event(struct tda998x_priv *priv, + int event) +{ + if (!priv->event) + return; + priv->event(priv->codec, event); +} + /* DRM encoder functions */ /* this function is not called when no info->platform (DT support) */ @@ -840,7 +896,7 @@ tda998x_encoder_set_config(struct drm_encoder *encoder, void *params) if (p->audio_cfg) { priv->audio_port = p->audio_cfg; - priv->audio_type = p->audio_format; + priv->audio_type = p->audio_format | AUDIO_ACTIVE; } } @@ -1105,9 +1161,10 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, tda998x_write_avi(priv, mode); - if (priv->audio_type) + if (priv->audio_type & AUDIO_ACTIVE) tda998x_configure_audio(priv, mode); } + send_audio_event(priv, priv->is_hdmi_sink); /* must be last register set: */ reg_write(priv, REG_TBG_CNTRL_0, 0); @@ -1263,6 +1320,7 @@ tda998x_encoder_get_modes(struct drm_encoder *encoder, drm_mode_connector_update_edid_property(connector, edid); n = drm_add_edid_modes(connector, edid); priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid); + send_audio_event(priv, priv->is_hdmi_sink); kfree(edid); } @@ -1349,6 +1407,8 @@ tda998x_encoder_init(struct i2c_client *client, if (!priv) return -ENOMEM; + i2c_set_clientdata(client, priv); + 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); -- Ken ar c'hentaƱ | ** Breizh ha Linux atav! ** Jef | http://moinejf.free.fr/