aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJyri Sarha <jsarha@ti.com>2016-08-09 15:00:05 -0400
committerRussell King <rmk+kernel@armlinux.org.uk>2016-09-07 08:10:10 -0400
commit7e567624dc5a44276d9df253f5ca829d911b4e93 (patch)
tree224f8e3f993b2824835e8610b210dab21ccd8c37
parent95db3b255fde4e830e5f8cc011eb404023f669d4 (diff)
drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding
Register ASoC HDMI codec for audio functionality and adds device tree binding for audio configuration. With the registered HDMI codec the tda998x node can be used like a regular codec node in ASoC card configurations. HDMI audio info-frame and audio stream header is generated by the ASoC HDMI codec. The codec also applies constraints for available sample-rates based on Edid Like Data from the display. The device tree binding document has been updated [1]. Part of this patch has been inspired by Jean Francoise's "drm/i2c: tda998x: Add support of a DT graph of ports"-patch [2]. There may still be some identical lines left from the original patch and some of the ideas have come from there. [1] Documentation/devicetree/bindings/display/bridge/tda998x.txt [2] http://mailman.alsa-project.org/pipermail/alsa-devel/2015-July/095255.html Signed-off-by: Jyri Sarha <jsarha@ti.com> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--Documentation/devicetree/bindings/display/bridge/tda998x.txt18
-rw-r--r--drivers/gpu/drm/i2c/Kconfig1
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c213
-rw-r--r--include/drm/i2c/tda998x.h5
-rw-r--r--include/dt-bindings/display/tda998x.h7
5 files changed, 239 insertions, 5 deletions
diff --git a/Documentation/devicetree/bindings/display/bridge/tda998x.txt b/Documentation/devicetree/bindings/display/bridge/tda998x.txt
index e178e6b9f9ee..24cc2466185a 100644
--- a/Documentation/devicetree/bindings/display/bridge/tda998x.txt
+++ b/Documentation/devicetree/bindings/display/bridge/tda998x.txt
@@ -21,8 +21,19 @@ Optional properties:
21 - video-ports: 24 bits value which defines how the video controller 21 - video-ports: 24 bits value which defines how the video controller
22 output is wired to the TDA998x input - default: <0x230145> 22 output is wired to the TDA998x input - default: <0x230145>
23 23
24 - audio-ports: array of 8-bit values, 2 values per one DAI[1].
25 The first value defines the DAI type: TDA998x_SPDIF or TDA998x_I2S[2].
26 The second value defines the tda998x AP_ENA reg content when the DAI
27 in question is used. The implementation allows one or two DAIs. If two
28 DAIs are defined, they must be of different type.
29
30[1] Documentation/sound/alsa/soc/DAI.txt
31[2] include/dt-bindings/display/tda998x.h
32
24Example: 33Example:
25 34
35#include <dt-bindings/display/tda998x.h>
36
26 tda998x: hdmi-encoder { 37 tda998x: hdmi-encoder {
27 compatible = "nxp,tda998x"; 38 compatible = "nxp,tda998x";
28 reg = <0x70>; 39 reg = <0x70>;
@@ -30,4 +41,11 @@ Example:
30 interrupts = <27 2>; /* falling edge */ 41 interrupts = <27 2>; /* falling edge */
31 pinctrl-0 = <&pmx_camera>; 42 pinctrl-0 = <&pmx_camera>;
32 pinctrl-names = "default"; 43 pinctrl-names = "default";
44 video-ports = <0x230145>;
45
46 #sound-dai-cells = <2>;
47 /* DAI-format AP_ENA reg value */
48 audio-ports = < TDA998x_SPDIF 0x04
49 TDA998x_I2S 0x03>;
50
33 }; 51 };
diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
index 22c7ed63a001..088f2781d303 100644
--- a/drivers/gpu/drm/i2c/Kconfig
+++ b/drivers/gpu/drm/i2c/Kconfig
@@ -28,6 +28,7 @@ config DRM_I2C_SIL164
28config DRM_I2C_NXP_TDA998X 28config DRM_I2C_NXP_TDA998X
29 tristate "NXP Semiconductors TDA998X HDMI encoder" 29 tristate "NXP Semiconductors TDA998X HDMI encoder"
30 default m if DRM_TILCDC 30 default m if DRM_TILCDC
31 select SND_SOC_HDMI_CODEC if SND_SOC
31 help 32 help
32 Support for NXP Semiconductors TDA998X HDMI encoders. 33 Support for NXP Semiconductors TDA998X HDMI encoders.
33 34
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index f7c414a76538..9798d400d817 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -20,6 +20,7 @@
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/irq.h> 21#include <linux/irq.h>
22#include <sound/asoundef.h> 22#include <sound/asoundef.h>
23#include <sound/hdmi-codec.h>
23 24
24#include <drm/drmP.h> 25#include <drm/drmP.h>
25#include <drm/drm_atomic_helper.h> 26#include <drm/drm_atomic_helper.h>
@@ -30,6 +31,11 @@
30 31
31#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) 32#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
32 33
34struct tda998x_audio_port {
35 u8 format; /* AFMT_xxx */
36 u8 config; /* AP value */
37};
38
33struct tda998x_priv { 39struct tda998x_priv {
34 struct i2c_client *cec; 40 struct i2c_client *cec;
35 struct i2c_client *hdmi; 41 struct i2c_client *hdmi;
@@ -43,6 +49,9 @@ struct tda998x_priv {
43 u8 vip_cntrl_2; 49 u8 vip_cntrl_2;
44 struct tda998x_audio_params audio_params; 50 struct tda998x_audio_params audio_params;
45 51
52 struct platform_device *audio_pdev;
53 struct mutex audio_mutex;
54
46 wait_queue_head_t wq_edid; 55 wait_queue_head_t wq_edid;
47 volatile int wq_edid_wait; 56 volatile int wq_edid_wait;
48 57
@@ -53,6 +62,8 @@ struct tda998x_priv {
53 62
54 struct drm_encoder encoder; 63 struct drm_encoder encoder;
55 struct drm_connector connector; 64 struct drm_connector connector;
65
66 struct tda998x_audio_port audio_port[2];
56}; 67};
57 68
58#define conn_to_tda998x_priv(x) \ 69#define conn_to_tda998x_priv(x) \
@@ -743,7 +754,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
743 break; 754 break;
744 755
745 default: 756 default:
746 BUG(); 757 dev_err(&priv->hdmi->dev, "Unsupported I2S format\n");
747 return -EINVAL; 758 return -EINVAL;
748 } 759 }
749 760
@@ -1064,9 +1075,11 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
1064 tda998x_write_avi(priv, adjusted_mode); 1075 tda998x_write_avi(priv, adjusted_mode);
1065 1076
1066 if (priv->audio_params.format != AFMT_UNUSED) { 1077 if (priv->audio_params.format != AFMT_UNUSED) {
1078 mutex_lock(&priv->audio_mutex);
1067 tda998x_configure_audio(priv, 1079 tda998x_configure_audio(priv,
1068 &priv->audio_params, 1080 &priv->audio_params,
1069 adjusted_mode->clock); 1081 adjusted_mode->clock);
1082 mutex_unlock(&priv->audio_mutex);
1070 } 1083 }
1071 } 1084 }
1072} 1085}
@@ -1167,6 +1180,8 @@ static int tda998x_connector_get_modes(struct drm_connector *connector)
1167 drm_mode_connector_update_edid_property(connector, edid); 1180 drm_mode_connector_update_edid_property(connector, edid);
1168 n = drm_add_edid_modes(connector, edid); 1181 n = drm_add_edid_modes(connector, edid);
1169 priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid); 1182 priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid);
1183 drm_edid_to_eld(connector, edid);
1184
1170 kfree(edid); 1185 kfree(edid);
1171 1186
1172 return n; 1187 return n;
@@ -1188,6 +1203,9 @@ static void tda998x_destroy(struct tda998x_priv *priv)
1188 cec_write(priv, REG_CEC_RXSHPDINTENA, 0); 1203 cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
1189 reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); 1204 reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
1190 1205
1206 if (priv->audio_pdev)
1207 platform_device_unregister(priv->audio_pdev);
1208
1191 if (priv->hdmi->irq) 1209 if (priv->hdmi->irq)
1192 free_irq(priv->hdmi->irq, priv); 1210 free_irq(priv->hdmi->irq, priv);
1193 1211
@@ -1197,8 +1215,189 @@ static void tda998x_destroy(struct tda998x_priv *priv)
1197 i2c_unregister_device(priv->cec); 1215 i2c_unregister_device(priv->cec);
1198} 1216}
1199 1217
1218static int tda998x_audio_hw_params(struct device *dev, void *data,
1219 struct hdmi_codec_daifmt *daifmt,
1220 struct hdmi_codec_params *params)
1221{
1222 struct tda998x_priv *priv = dev_get_drvdata(dev);
1223 int i, ret;
1224 struct tda998x_audio_params audio = {
1225 .sample_width = params->sample_width,
1226 .sample_rate = params->sample_rate,
1227 .cea = params->cea,
1228 };
1229
1230 if (!priv->encoder.crtc)
1231 return -ENODEV;
1232
1233 memcpy(audio.status, params->iec.status,
1234 min(sizeof(audio.status), sizeof(params->iec.status)));
1235
1236 switch (daifmt->fmt) {
1237 case HDMI_I2S:
1238 if (daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
1239 daifmt->bit_clk_master || daifmt->frame_clk_master) {
1240 dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
1241 daifmt->bit_clk_inv, daifmt->frame_clk_inv,
1242 daifmt->bit_clk_master,
1243 daifmt->frame_clk_master);
1244 return -EINVAL;
1245 }
1246 for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
1247 if (priv->audio_port[i].format == AFMT_I2S)
1248 audio.config = priv->audio_port[i].config;
1249 audio.format = AFMT_I2S;
1250 break;
1251 case HDMI_SPDIF:
1252 for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
1253 if (priv->audio_port[i].format == AFMT_SPDIF)
1254 audio.config = priv->audio_port[i].config;
1255 audio.format = AFMT_SPDIF;
1256 break;
1257 default:
1258 dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt);
1259 return -EINVAL;
1260 }
1261
1262 if (audio.config == 0) {
1263 dev_err(dev, "%s: No audio configutation found\n", __func__);
1264 return -EINVAL;
1265 }
1266
1267 mutex_lock(&priv->audio_mutex);
1268 ret = tda998x_configure_audio(priv,
1269 &audio,
1270 priv->encoder.crtc->hwmode.clock);
1271
1272 if (ret == 0)
1273 priv->audio_params = audio;
1274 mutex_unlock(&priv->audio_mutex);
1275
1276 return ret;
1277}
1278
1279static void tda998x_audio_shutdown(struct device *dev, void *data)
1280{
1281 struct tda998x_priv *priv = dev_get_drvdata(dev);
1282
1283 mutex_lock(&priv->audio_mutex);
1284
1285 reg_write(priv, REG_ENA_AP, 0);
1286
1287 priv->audio_params.format = AFMT_UNUSED;
1288
1289 mutex_unlock(&priv->audio_mutex);
1290}
1291
1292int tda998x_audio_digital_mute(struct device *dev, void *data, bool enable)
1293{
1294 struct tda998x_priv *priv = dev_get_drvdata(dev);
1295
1296 mutex_lock(&priv->audio_mutex);
1297
1298 tda998x_audio_mute(priv, enable);
1299
1300 mutex_unlock(&priv->audio_mutex);
1301 return 0;
1302}
1303
1304static int tda998x_audio_get_eld(struct device *dev, void *data,
1305 uint8_t *buf, size_t len)
1306{
1307 struct tda998x_priv *priv = dev_get_drvdata(dev);
1308 struct drm_mode_config *config = &priv->encoder.dev->mode_config;
1309 struct drm_connector *connector;
1310 int ret = -ENODEV;
1311
1312 mutex_lock(&config->mutex);
1313 list_for_each_entry(connector, &config->connector_list, head) {
1314 if (&priv->encoder == connector->encoder) {
1315 memcpy(buf, connector->eld,
1316 min(sizeof(connector->eld), len));
1317 ret = 0;
1318 }
1319 }
1320 mutex_unlock(&config->mutex);
1321
1322 return ret;
1323}
1324
1325static const struct hdmi_codec_ops audio_codec_ops = {
1326 .hw_params = tda998x_audio_hw_params,
1327 .audio_shutdown = tda998x_audio_shutdown,
1328 .digital_mute = tda998x_audio_digital_mute,
1329 .get_eld = tda998x_audio_get_eld,
1330};
1331
1332static int tda998x_audio_codec_init(struct tda998x_priv *priv,
1333 struct device *dev)
1334{
1335 struct hdmi_codec_pdata codec_data = {
1336 .ops = &audio_codec_ops,
1337 .max_i2s_channels = 2,
1338 };
1339 int i;
1340
1341 for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++) {
1342 if (priv->audio_port[i].format == AFMT_I2S &&
1343 priv->audio_port[i].config != 0)
1344 codec_data.i2s = 1;
1345 if (priv->audio_port[i].format == AFMT_SPDIF &&
1346 priv->audio_port[i].config != 0)
1347 codec_data.spdif = 1;
1348 }
1349
1350 priv->audio_pdev = platform_device_register_data(
1351 dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
1352 &codec_data, sizeof(codec_data));
1353
1354 return PTR_ERR_OR_ZERO(priv->audio_pdev);
1355}
1356
1200/* I2C driver functions */ 1357/* I2C driver functions */
1201 1358
1359static int tda998x_get_audio_ports(struct tda998x_priv *priv,
1360 struct device_node *np)
1361{
1362 const u32 *port_data;
1363 u32 size;
1364 int i;
1365
1366 port_data = of_get_property(np, "audio-ports", &size);
1367 if (!port_data)
1368 return 0;
1369
1370 size /= sizeof(u32);
1371 if (size > 2 * ARRAY_SIZE(priv->audio_port) || size % 2 != 0) {
1372 dev_err(&priv->hdmi->dev,
1373 "Bad number of elements in audio-ports dt-property\n");
1374 return -EINVAL;
1375 }
1376
1377 size /= 2;
1378
1379 for (i = 0; i < size; i++) {
1380 u8 afmt = be32_to_cpup(&port_data[2*i]);
1381 u8 ena_ap = be32_to_cpup(&port_data[2*i+1]);
1382
1383 if (afmt != AFMT_SPDIF && afmt != AFMT_I2S) {
1384 dev_err(&priv->hdmi->dev,
1385 "Bad audio format %u\n", afmt);
1386 return -EINVAL;
1387 }
1388
1389 priv->audio_port[i].format = afmt;
1390 priv->audio_port[i].config = ena_ap;
1391 }
1392
1393 if (priv->audio_port[0].format == priv->audio_port[1].format) {
1394 dev_err(&priv->hdmi->dev,
1395 "There can only be on I2S port and one SPDIF port\n");
1396 return -EINVAL;
1397 }
1398 return 0;
1399}
1400
1202static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) 1401static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
1203{ 1402{
1204 struct device_node *np = client->dev.of_node; 1403 struct device_node *np = client->dev.of_node;
@@ -1312,7 +1511,7 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
1312 if (!np) 1511 if (!np)
1313 return 0; /* non-DT */ 1512 return 0; /* non-DT */
1314 1513
1315 /* get the optional video properties */ 1514 /* get the device tree parameters */
1316 ret = of_property_read_u32(np, "video-ports", &video); 1515 ret = of_property_read_u32(np, "video-ports", &video);
1317 if (ret == 0) { 1516 if (ret == 0) {
1318 priv->vip_cntrl_0 = video >> 16; 1517 priv->vip_cntrl_0 = video >> 16;
@@ -1320,8 +1519,16 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
1320 priv->vip_cntrl_2 = video; 1519 priv->vip_cntrl_2 = video;
1321 } 1520 }
1322 1521
1323 return 0; 1522 mutex_init(&priv->audio_mutex); /* Protect access from audio thread */
1324 1523
1524 ret = tda998x_get_audio_ports(priv, np);
1525 if (ret)
1526 goto fail;
1527
1528 if (priv->audio_port[0].format != AFMT_UNUSED)
1529 tda998x_audio_codec_init(priv, &client->dev);
1530
1531 return 0;
1325fail: 1532fail:
1326 /* if encoder_init fails, the encoder slave is never registered, 1533 /* if encoder_init fails, the encoder slave is never registered,
1327 * so cleanup here: 1534 * so cleanup here:
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
index a8dc06e67b03..a25483090cd5 100644
--- a/include/drm/i2c/tda998x.h
+++ b/include/drm/i2c/tda998x.h
@@ -2,11 +2,12 @@
2#define __DRM_I2C_TDA998X_H__ 2#define __DRM_I2C_TDA998X_H__
3 3
4#include <linux/hdmi.h> 4#include <linux/hdmi.h>
5#include <dt-bindings/display/tda998x.h>
5 6
6enum { 7enum {
7 AFMT_UNUSED = 0, 8 AFMT_UNUSED = 0,
8 AFMT_SPDIF = 1, 9 AFMT_SPDIF = TDA998x_SPDIF,
9 AFMT_I2S = 2, 10 AFMT_I2S = TDA998x_I2S,
10}; 11};
11 12
12struct tda998x_audio_params { 13struct tda998x_audio_params {
diff --git a/include/dt-bindings/display/tda998x.h b/include/dt-bindings/display/tda998x.h
new file mode 100644
index 000000000000..34757a3847ef
--- /dev/null
+++ b/include/dt-bindings/display/tda998x.h
@@ -0,0 +1,7 @@
1#ifndef _DT_BINDINGS_TDA998X_H
2#define _DT_BINDINGS_TDA998X_H
3
4#define TDA998x_SPDIF 1
5#define TDA998x_I2S 2
6
7#endif /*_DT_BINDINGS_TDA998X_H */