4 * Copyright (c) 2017 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 #include <drm/bridge/dw_hdmi.h>
13 #include <sound/hdmi-codec.h>
16 #include "dw-hdmi-audio.h"
18 #define DRIVER_NAME "dw-hdmi-i2s-audio"
20 static inline void hdmi_write(struct dw_hdmi_i2s_audio_data
*audio
,
23 struct dw_hdmi
*hdmi
= audio
->hdmi
;
25 audio
->write(hdmi
, val
, offset
);
28 static inline u8
hdmi_read(struct dw_hdmi_i2s_audio_data
*audio
, int offset
)
30 struct dw_hdmi
*hdmi
= audio
->hdmi
;
32 return audio
->read(hdmi
, offset
);
35 static int dw_hdmi_i2s_hw_params(struct device
*dev
, void *data
,
36 struct hdmi_codec_daifmt
*fmt
,
37 struct hdmi_codec_params
*hparms
)
39 struct dw_hdmi_i2s_audio_data
*audio
= data
;
40 struct dw_hdmi
*hdmi
= audio
->hdmi
;
45 /* it cares I2S only */
46 if ((fmt
->fmt
!= HDMI_I2S
) ||
47 (fmt
->bit_clk_master
| fmt
->frame_clk_master
)) {
48 dev_err(dev
, "unsupported format/settings\n");
52 inputclkfs
= HDMI_AUD_INPUTCLKFS_64FS
;
53 conf0
= HDMI_AUD_CONF0_I2S_ALL_ENABLE
;
55 switch (hparms
->sample_width
) {
57 conf1
= HDMI_AUD_CONF1_WIDTH_16
;
61 conf1
= HDMI_AUD_CONF1_WIDTH_24
;
65 dw_hdmi_set_sample_rate(hdmi
, hparms
->sample_rate
);
67 hdmi_write(audio
, inputclkfs
, HDMI_AUD_INPUTCLKFS
);
68 hdmi_write(audio
, conf0
, HDMI_AUD_CONF0
);
69 hdmi_write(audio
, conf1
, HDMI_AUD_CONF1
);
71 dw_hdmi_audio_enable(hdmi
);
76 static void dw_hdmi_i2s_audio_shutdown(struct device
*dev
, void *data
)
78 struct dw_hdmi_i2s_audio_data
*audio
= data
;
79 struct dw_hdmi
*hdmi
= audio
->hdmi
;
81 dw_hdmi_audio_disable(hdmi
);
83 hdmi_write(audio
, HDMI_AUD_CONF0_SW_RESET
, HDMI_AUD_CONF0
);
86 static int dw_hdmi_i2s_get_dai_id(struct snd_soc_component
*component
,
87 struct device_node
*endpoint
)
89 struct of_endpoint of_ep
;
92 ret
= of_graph_parse_endpoint(endpoint
, &of_ep
);
97 * HDMI sound should be located as reg = <2>
98 * Then, it is sound port 0
106 static struct hdmi_codec_ops dw_hdmi_i2s_ops
= {
107 .hw_params
= dw_hdmi_i2s_hw_params
,
108 .audio_shutdown
= dw_hdmi_i2s_audio_shutdown
,
109 .get_dai_id
= dw_hdmi_i2s_get_dai_id
,
112 static int snd_dw_hdmi_probe(struct platform_device
*pdev
)
114 struct dw_hdmi_i2s_audio_data
*audio
= pdev
->dev
.platform_data
;
115 struct platform_device_info pdevinfo
;
116 struct hdmi_codec_pdata pdata
;
117 struct platform_device
*platform
;
119 pdata
.ops
= &dw_hdmi_i2s_ops
;
121 pdata
.max_i2s_channels
= 6;
124 memset(&pdevinfo
, 0, sizeof(pdevinfo
));
125 pdevinfo
.parent
= pdev
->dev
.parent
;
126 pdevinfo
.id
= PLATFORM_DEVID_AUTO
;
127 pdevinfo
.name
= HDMI_CODEC_DRV_NAME
;
128 pdevinfo
.data
= &pdata
;
129 pdevinfo
.size_data
= sizeof(pdata
);
130 pdevinfo
.dma_mask
= DMA_BIT_MASK(32);
132 platform
= platform_device_register_full(&pdevinfo
);
133 if (IS_ERR(platform
))
134 return PTR_ERR(platform
);
136 dev_set_drvdata(&pdev
->dev
, platform
);
141 static int snd_dw_hdmi_remove(struct platform_device
*pdev
)
143 struct platform_device
*platform
= dev_get_drvdata(&pdev
->dev
);
145 platform_device_unregister(platform
);
150 static struct platform_driver snd_dw_hdmi_driver
= {
151 .probe
= snd_dw_hdmi_probe
,
152 .remove
= snd_dw_hdmi_remove
,
155 .owner
= THIS_MODULE
,
158 module_platform_driver(snd_dw_hdmi_driver
);
160 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
161 MODULE_DESCRIPTION("Synopsis Designware HDMI I2S ALSA SoC interface");
162 MODULE_LICENSE("GPL v2");
163 MODULE_ALIAS("platform:" DRIVER_NAME
);