aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i2c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-09-12 20:28:17 -0400
committerDave Airlie <airlied@redhat.com>2016-09-12 20:28:17 -0400
commit8506912b969b60aacc733315eeeb46b014d920a4 (patch)
tree42a786a5e6d20470f9eec8cd2614d9e827505a9c /drivers/gpu/drm/i2c
parentb4eac5465b23a9bcb4a66376a5664086b4913288 (diff)
parentdf0bd1e8f3c508bf4c3445f94b12e38289b65f13 (diff)
Merge branch 'drm-tda998x-devel' of git://git.armlinux.org.uk/~rmk/linux-arm into drm-next
This adds the ASoC codec interfaces for TDA998x HDMI audio from Jyri Sarha. * 'drm-tda998x-devel' of git://git.armlinux.org.uk/~rmk/linux-arm: ARM: dts: am335x-boneblack: Add HDMI audio support drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding drm/i2c: tda998x: Improve tda998x_configure_audio() audio related pdata
Diffstat (limited to 'drivers/gpu/drm/i2c')
-rw-r--r--drivers/gpu/drm/i2c/Kconfig1
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c297
2 files changed, 257 insertions, 41 deletions
diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
index 4d341db462a2..a6c92beb410a 100644
--- a/drivers/gpu/drm/i2c/Kconfig
+++ b/drivers/gpu/drm/i2c/Kconfig
@@ -22,6 +22,7 @@ config DRM_I2C_SIL164
22config DRM_I2C_NXP_TDA998X 22config DRM_I2C_NXP_TDA998X
23 tristate "NXP Semiconductors TDA998X HDMI encoder" 23 tristate "NXP Semiconductors TDA998X HDMI encoder"
24 default m if DRM_TILCDC 24 default m if DRM_TILCDC
25 select SND_SOC_HDMI_CODEC if SND_SOC
25 help 26 help
26 Support for NXP Semiconductors TDA998X HDMI encoders. 27 Support for NXP Semiconductors TDA998X HDMI encoders.
27 28
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index f4315bc8d471..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;
@@ -41,7 +47,10 @@ struct tda998x_priv {
41 u8 vip_cntrl_0; 47 u8 vip_cntrl_0;
42 u8 vip_cntrl_1; 48 u8 vip_cntrl_1;
43 u8 vip_cntrl_2; 49 u8 vip_cntrl_2;
44 struct tda998x_encoder_params params; 50 struct tda998x_audio_params audio_params;
51
52 struct platform_device *audio_pdev;
53 struct mutex audio_mutex;
45 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;
@@ -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) \
@@ -666,26 +677,16 @@ tda998x_write_if(struct tda998x_priv *priv, u8 bit, u16 addr,
666 reg_set(priv, REG_DIP_IF_FLAGS, bit); 677 reg_set(priv, REG_DIP_IF_FLAGS, bit);
667} 678}
668 679
669static void 680static int tda998x_write_aif(struct tda998x_priv *priv,
670tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p) 681 struct hdmi_audio_infoframe *cea)
671{ 682{
672 union hdmi_infoframe frame; 683 union hdmi_infoframe frame;
673 684
674 hdmi_audio_infoframe_init(&frame.audio); 685 frame.audio = *cea;
675
676 frame.audio.channels = p->audio_frame[1] & 0x07;
677 frame.audio.channel_allocation = p->audio_frame[4];
678 frame.audio.level_shift_value = (p->audio_frame[5] & 0x78) >> 3;
679 frame.audio.downmix_inhibit = (p->audio_frame[5] & 0x80) >> 7;
680
681 /*
682 * L-PCM and IEC61937 compressed audio shall always set sample
683 * frequency to "refer to stream". For others, see the HDMI
684 * specification.
685 */
686 frame.audio.sample_frequency = (p->audio_frame[2] & 0x1c) >> 2;
687 686
688 tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, &frame); 687 tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, &frame);
688
689 return 0;
689} 690}
690 691
691static void 692static void
@@ -710,20 +711,21 @@ static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
710 } 711 }
711} 712}
712 713
713static void 714static int
714tda998x_configure_audio(struct tda998x_priv *priv, 715tda998x_configure_audio(struct tda998x_priv *priv,
715 struct drm_display_mode *mode, struct tda998x_encoder_params *p) 716 struct tda998x_audio_params *params,
717 unsigned mode_clock)
716{ 718{
717 u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv; 719 u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv;
718 u32 n; 720 u32 n;
719 721
720 /* Enable audio ports */ 722 /* Enable audio ports */
721 reg_write(priv, REG_ENA_AP, p->audio_cfg); 723 reg_write(priv, REG_ENA_AP, params->config);
722 reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg);
723 724
724 /* Set audio input source */ 725 /* Set audio input source */
725 switch (p->audio_format) { 726 switch (params->format) {
726 case AFMT_SPDIF: 727 case AFMT_SPDIF:
728 reg_write(priv, REG_ENA_ACLK, 0);
727 reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF); 729 reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF);
728 clksel_aip = AIP_CLKSEL_AIP_SPDIF; 730 clksel_aip = AIP_CLKSEL_AIP_SPDIF;
729 clksel_fs = AIP_CLKSEL_FS_FS64SPDIF; 731 clksel_fs = AIP_CLKSEL_FS_FS64SPDIF;
@@ -731,15 +733,29 @@ tda998x_configure_audio(struct tda998x_priv *priv,
731 break; 733 break;
732 734
733 case AFMT_I2S: 735 case AFMT_I2S:
736 reg_write(priv, REG_ENA_ACLK, 1);
734 reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S); 737 reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S);
735 clksel_aip = AIP_CLKSEL_AIP_I2S; 738 clksel_aip = AIP_CLKSEL_AIP_I2S;
736 clksel_fs = AIP_CLKSEL_FS_ACLK; 739 clksel_fs = AIP_CLKSEL_FS_ACLK;
737 cts_n = CTS_N_M(3) | CTS_N_K(3); 740 switch (params->sample_width) {
741 case 16:
742 cts_n = CTS_N_M(3) | CTS_N_K(1);
743 break;
744 case 18:
745 case 20:
746 case 24:
747 cts_n = CTS_N_M(3) | CTS_N_K(2);
748 break;
749 default:
750 case 32:
751 cts_n = CTS_N_M(3) | CTS_N_K(3);
752 break;
753 }
738 break; 754 break;
739 755
740 default: 756 default:
741 BUG(); 757 dev_err(&priv->hdmi->dev, "Unsupported I2S format\n");
742 return; 758 return -EINVAL;
743 } 759 }
744 760
745 reg_write(priv, REG_AIP_CLKSEL, clksel_aip); 761 reg_write(priv, REG_AIP_CLKSEL, clksel_aip);
@@ -755,11 +771,11 @@ tda998x_configure_audio(struct tda998x_priv *priv,
755 * assume 100MHz requires larger divider. 771 * assume 100MHz requires larger divider.
756 */ 772 */
757 adiv = AUDIO_DIV_SERCLK_8; 773 adiv = AUDIO_DIV_SERCLK_8;
758 if (mode->clock > 100000) 774 if (mode_clock > 100000)
759 adiv++; /* AUDIO_DIV_SERCLK_16 */ 775 adiv++; /* AUDIO_DIV_SERCLK_16 */
760 776
761 /* S/PDIF asks for a larger divider */ 777 /* S/PDIF asks for a larger divider */
762 if (p->audio_format == AFMT_SPDIF) 778 if (params->format == AFMT_SPDIF)
763 adiv++; /* AUDIO_DIV_SERCLK_16 or _32 */ 779 adiv++; /* AUDIO_DIV_SERCLK_16 or _32 */
764 780
765 reg_write(priv, REG_AUDIO_DIV, adiv); 781 reg_write(priv, REG_AUDIO_DIV, adiv);
@@ -768,7 +784,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
768 * This is the approximate value of N, which happens to be 784 * This is the approximate value of N, which happens to be
769 * the recommended values for non-coherent clocks. 785 * the recommended values for non-coherent clocks.
770 */ 786 */
771 n = 128 * p->audio_sample_rate / 1000; 787 n = 128 * params->sample_rate / 1000;
772 788
773 /* Write the CTS and N values */ 789 /* Write the CTS and N values */
774 buf[0] = 0x44; 790 buf[0] = 0x44;
@@ -786,20 +802,21 @@ tda998x_configure_audio(struct tda998x_priv *priv,
786 reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS); 802 reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
787 reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS); 803 reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
788 804
789 /* Write the channel status */ 805 /* Write the channel status
790 buf[0] = IEC958_AES0_CON_NOT_COPYRIGHT; 806 * The REG_CH_STAT_B-registers skip IEC958 AES2 byte, because
791 buf[1] = 0x00; 807 * there is a separate register for each I2S wire.
792 buf[2] = IEC958_AES3_CON_FS_NOTID; 808 */
793 buf[3] = IEC958_AES4_CON_ORIGFS_NOTID | 809 buf[0] = params->status[0];
794 IEC958_AES4_CON_MAX_WORDLEN_24; 810 buf[1] = params->status[1];
811 buf[2] = params->status[3];
812 buf[3] = params->status[4];
795 reg_write_range(priv, REG_CH_STAT_B(0), buf, 4); 813 reg_write_range(priv, REG_CH_STAT_B(0), buf, 4);
796 814
797 tda998x_audio_mute(priv, true); 815 tda998x_audio_mute(priv, true);
798 msleep(20); 816 msleep(20);
799 tda998x_audio_mute(priv, false); 817 tda998x_audio_mute(priv, false);
800 818
801 /* Write the audio information packet */ 819 return tda998x_write_aif(priv, &params->cea);
802 tda998x_write_aif(priv, p);
803} 820}
804 821
805/* DRM encoder functions */ 822/* DRM encoder functions */
@@ -820,7 +837,7 @@ static void tda998x_encoder_set_config(struct tda998x_priv *priv,
820 VIP_CNTRL_2_SWAP_F(p->swap_f) | 837 VIP_CNTRL_2_SWAP_F(p->swap_f) |
821 (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0); 838 (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
822 839
823 priv->params = *p; 840 priv->audio_params = p->audio_params;
824} 841}
825 842
826static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode) 843static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
@@ -1057,9 +1074,13 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
1057 1074
1058 tda998x_write_avi(priv, adjusted_mode); 1075 tda998x_write_avi(priv, adjusted_mode);
1059 1076
1060 if (priv->params.audio_cfg) 1077 if (priv->audio_params.format != AFMT_UNUSED) {
1061 tda998x_configure_audio(priv, adjusted_mode, 1078 mutex_lock(&priv->audio_mutex);
1062 &priv->params); 1079 tda998x_configure_audio(priv,
1080 &priv->audio_params,
1081 adjusted_mode->clock);
1082 mutex_unlock(&priv->audio_mutex);
1083 }
1063 } 1084 }
1064} 1085}
1065 1086
@@ -1159,6 +1180,8 @@ static int tda998x_connector_get_modes(struct drm_connector *connector)
1159 drm_mode_connector_update_edid_property(connector, edid); 1180 drm_mode_connector_update_edid_property(connector, edid);
1160 n = drm_add_edid_modes(connector, edid); 1181 n = drm_add_edid_modes(connector, edid);
1161 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
1162 kfree(edid); 1185 kfree(edid);
1163 1186
1164 return n; 1187 return n;
@@ -1180,6 +1203,9 @@ static void tda998x_destroy(struct tda998x_priv *priv)
1180 cec_write(priv, REG_CEC_RXSHPDINTENA, 0); 1203 cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
1181 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);
1182 1205
1206 if (priv->audio_pdev)
1207 platform_device_unregister(priv->audio_pdev);
1208
1183 if (priv->hdmi->irq) 1209 if (priv->hdmi->irq)
1184 free_irq(priv->hdmi->irq, priv); 1210 free_irq(priv->hdmi->irq, priv);
1185 1211
@@ -1189,8 +1215,189 @@ static void tda998x_destroy(struct tda998x_priv *priv)
1189 i2c_unregister_device(priv->cec); 1215 i2c_unregister_device(priv->cec);
1190} 1216}
1191 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
1192/* I2C driver functions */ 1357/* I2C driver functions */
1193 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
1194static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) 1401static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
1195{ 1402{
1196 struct device_node *np = client->dev.of_node; 1403 struct device_node *np = client->dev.of_node;
@@ -1304,7 +1511,7 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
1304 if (!np) 1511 if (!np)
1305 return 0; /* non-DT */ 1512 return 0; /* non-DT */
1306 1513
1307 /* get the optional video properties */ 1514 /* get the device tree parameters */
1308 ret = of_property_read_u32(np, "video-ports", &video); 1515 ret = of_property_read_u32(np, "video-ports", &video);
1309 if (ret == 0) { 1516 if (ret == 0) {
1310 priv->vip_cntrl_0 = video >> 16; 1517 priv->vip_cntrl_0 = video >> 16;
@@ -1312,8 +1519,16 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
1312 priv->vip_cntrl_2 = video; 1519 priv->vip_cntrl_2 = video;
1313 } 1520 }
1314 1521
1315 return 0; 1522 mutex_init(&priv->audio_mutex); /* Protect access from audio thread */
1316 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;
1317fail: 1532fail:
1318 /* if encoder_init fails, the encoder slave is never registered, 1533 /* if encoder_init fails, the encoder slave is never registered,
1319 * so cleanup here: 1534 * so cleanup here: