4 * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 #include <drm/bridge/dw_hdmi.h>
12 #include <sound/hdmi-codec.h>
15 #include "dw-hdmi-audio.h"
17 #define DRIVER_NAME "dw-hdmi-i2s-audio"
19 static inline void hdmi_write(struct dw_hdmi_i2s_audio_data
*audio
,
22 struct dw_hdmi
*hdmi
= audio
->hdmi
;
24 audio
->write(hdmi
, val
, offset
);
27 static inline u8
hdmi_read(struct dw_hdmi_i2s_audio_data
*audio
, int offset
)
29 struct dw_hdmi
*hdmi
= audio
->hdmi
;
31 return audio
->read(hdmi
, offset
);
34 static int dw_hdmi_i2s_hw_params(struct device
*dev
, void *data
,
35 struct hdmi_codec_daifmt
*fmt
,
36 struct hdmi_codec_params
*hparms
)
38 struct dw_hdmi_i2s_audio_data
*audio
= data
;
39 struct dw_hdmi
*hdmi
= audio
->hdmi
;
44 /* it cares I2S only */
45 if ((fmt
->fmt
!= HDMI_I2S
) ||
46 (fmt
->bit_clk_master
| fmt
->frame_clk_master
)) {
47 dev_err(dev
, "unsupported format/settings\n");
51 inputclkfs
= HDMI_AUD_INPUTCLKFS_64FS
;
52 conf0
= HDMI_AUD_CONF0_I2S_ALL_ENABLE
;
54 switch (hparms
->sample_width
) {
56 conf1
= HDMI_AUD_CONF1_WIDTH_16
;
60 conf1
= HDMI_AUD_CONF1_WIDTH_24
;
64 dw_hdmi_set_sample_rate(hdmi
, hparms
->sample_rate
);
66 hdmi_write(audio
, inputclkfs
, HDMI_AUD_INPUTCLKFS
);
67 hdmi_write(audio
, conf0
, HDMI_AUD_CONF0
);
68 hdmi_write(audio
, conf1
, HDMI_AUD_CONF1
);
70 dw_hdmi_audio_enable(hdmi
);
75 static void dw_hdmi_i2s_audio_shutdown(struct device
*dev
, void *data
)
77 struct dw_hdmi_i2s_audio_data
*audio
= data
;
78 struct dw_hdmi
*hdmi
= audio
->hdmi
;
80 dw_hdmi_audio_disable(hdmi
);
82 hdmi_write(audio
, HDMI_AUD_CONF0_SW_RESET
, HDMI_AUD_CONF0
);
85 static int dw_hdmi_i2s_get_dai_id(struct snd_soc_component
*component
,
86 struct device_node
*endpoint
)
88 struct of_endpoint of_ep
;
91 ret
= of_graph_parse_endpoint(endpoint
, &of_ep
);
96 * HDMI sound should be located as reg = <2>
97 * Then, it is sound port 0
105 static struct hdmi_codec_ops dw_hdmi_i2s_ops
= {
106 .hw_params
= dw_hdmi_i2s_hw_params
,
107 .audio_shutdown
= dw_hdmi_i2s_audio_shutdown
,
108 .get_dai_id
= dw_hdmi_i2s_get_dai_id
,
111 static int snd_dw_hdmi_probe(struct platform_device
*pdev
)
113 struct dw_hdmi_i2s_audio_data
*audio
= pdev
->dev
.platform_data
;
114 struct platform_device_info pdevinfo
;
115 struct hdmi_codec_pdata pdata
;
116 struct platform_device
*platform
;
118 pdata
.ops
= &dw_hdmi_i2s_ops
;
120 pdata
.max_i2s_channels
= 6;
123 memset(&pdevinfo
, 0, sizeof(pdevinfo
));
124 pdevinfo
.parent
= pdev
->dev
.parent
;
125 pdevinfo
.id
= PLATFORM_DEVID_AUTO
;
126 pdevinfo
.name
= HDMI_CODEC_DRV_NAME
;
127 pdevinfo
.data
= &pdata
;
128 pdevinfo
.size_data
= sizeof(pdata
);
129 pdevinfo
.dma_mask
= DMA_BIT_MASK(32);
131 platform
= platform_device_register_full(&pdevinfo
);
132 if (IS_ERR(platform
))
133 return PTR_ERR(platform
);
135 dev_set_drvdata(&pdev
->dev
, platform
);
140 static int snd_dw_hdmi_remove(struct platform_device
*pdev
)
142 struct platform_device
*platform
= dev_get_drvdata(&pdev
->dev
);
144 platform_device_unregister(platform
);
149 static struct platform_driver snd_dw_hdmi_driver
= {
150 .probe
= snd_dw_hdmi_probe
,
151 .remove
= snd_dw_hdmi_remove
,
154 .owner
= THIS_MODULE
,
157 module_platform_driver(snd_dw_hdmi_driver
);
159 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
160 MODULE_DESCRIPTION("Synopsis Designware HDMI I2S ALSA SoC interface");
161 MODULE_LICENSE("GPL v2");
162 MODULE_ALIAS("platform:" DRIVER_NAME
);