diff options
Diffstat (limited to 'drivers/video/sh_mobile_hdmi.c')
-rw-r--r-- | drivers/video/sh_mobile_hdmi.c | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 2fde08cc66bf..ef989d94511c 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
25 | #include <sound/soc-dapm.h> | ||
26 | #include <sound/initval.h> | ||
25 | 27 | ||
26 | #include <video/sh_mobile_hdmi.h> | 28 | #include <video/sh_mobile_hdmi.h> |
27 | #include <video/sh_mobile_lcdc.h> | 29 | #include <video/sh_mobile_lcdc.h> |
@@ -222,6 +224,58 @@ static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg) | |||
222 | return ioread8(hdmi->base + reg); | 224 | return ioread8(hdmi->base + reg); |
223 | } | 225 | } |
224 | 226 | ||
227 | /* | ||
228 | * HDMI sound | ||
229 | */ | ||
230 | static unsigned int sh_hdmi_snd_read(struct snd_soc_codec *codec, | ||
231 | unsigned int reg) | ||
232 | { | ||
233 | struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec); | ||
234 | |||
235 | return hdmi_read(hdmi, reg); | ||
236 | } | ||
237 | |||
238 | static int sh_hdmi_snd_write(struct snd_soc_codec *codec, | ||
239 | unsigned int reg, | ||
240 | unsigned int value) | ||
241 | { | ||
242 | struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec); | ||
243 | |||
244 | hdmi_write(hdmi, value, reg); | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static struct snd_soc_dai_driver sh_hdmi_dai = { | ||
249 | .name = "sh_mobile_hdmi-hifi", | ||
250 | .playback = { | ||
251 | .stream_name = "Playback", | ||
252 | .channels_min = 2, | ||
253 | .channels_max = 8, | ||
254 | .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | | ||
255 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | | ||
256 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | | ||
257 | SNDRV_PCM_RATE_192000, | ||
258 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
259 | }, | ||
260 | }; | ||
261 | |||
262 | static int sh_hdmi_snd_probe(struct snd_soc_codec *codec) | ||
263 | { | ||
264 | dev_info(codec->dev, "SH Mobile HDMI Audio Codec"); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = { | ||
270 | .probe = sh_hdmi_snd_probe, | ||
271 | .read = sh_hdmi_snd_read, | ||
272 | .write = sh_hdmi_snd_write, | ||
273 | }; | ||
274 | |||
275 | /* | ||
276 | * HDMI video | ||
277 | */ | ||
278 | |||
225 | /* External video parameter settings */ | 279 | /* External video parameter settings */ |
226 | static void hdmi_external_video_param(struct sh_hdmi *hdmi) | 280 | static void hdmi_external_video_param(struct sh_hdmi *hdmi) |
227 | { | 281 | { |
@@ -318,6 +372,9 @@ static void sh_hdmi_video_config(struct sh_hdmi *hdmi) | |||
318 | */ | 372 | */ |
319 | static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) | 373 | static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) |
320 | { | 374 | { |
375 | u8 data; | ||
376 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | ||
377 | |||
321 | /* | 378 | /* |
322 | * [7:4] L/R data swap control | 379 | * [7:4] L/R data swap control |
323 | * [3:0] appropriate N[19:16] | 380 | * [3:0] appropriate N[19:16] |
@@ -335,7 +392,23 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) | |||
335 | * [6:5] set required down sampling rate if required | 392 | * [6:5] set required down sampling rate if required |
336 | * [4:3] set required audio source | 393 | * [4:3] set required audio source |
337 | */ | 394 | */ |
338 | hdmi_write(hdmi, 0x00, HDMI_AUDIO_SETTING_1); | 395 | switch (pdata->flags & HDMI_SND_SRC_MASK) { |
396 | default: | ||
397 | /* fall through */ | ||
398 | case HDMI_SND_SRC_I2S: | ||
399 | data = 0x0 << 3; | ||
400 | break; | ||
401 | case HDMI_SND_SRC_SPDIF: | ||
402 | data = 0x1 << 3; | ||
403 | break; | ||
404 | case HDMI_SND_SRC_DSD: | ||
405 | data = 0x2 << 3; | ||
406 | break; | ||
407 | case HDMI_SND_SRC_HBR: | ||
408 | data = 0x3 << 3; | ||
409 | break; | ||
410 | } | ||
411 | hdmi_write(hdmi, data, HDMI_AUDIO_SETTING_1); | ||
339 | 412 | ||
340 | /* [3:0] set sending channel number for channel status */ | 413 | /* [3:0] set sending channel number for channel status */ |
341 | hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2); | 414 | hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2); |
@@ -891,6 +964,11 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
891 | return -ENOMEM; | 964 | return -ENOMEM; |
892 | } | 965 | } |
893 | 966 | ||
967 | ret = snd_soc_register_codec(&pdev->dev, | ||
968 | &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1); | ||
969 | if (ret < 0) | ||
970 | goto esndreg; | ||
971 | |||
894 | hdmi->dev = &pdev->dev; | 972 | hdmi->dev = &pdev->dev; |
895 | 973 | ||
896 | hdmi->hdmi_clk = clk_get(&pdev->dev, "ick"); | 974 | hdmi->hdmi_clk = clk_get(&pdev->dev, "ick"); |
@@ -976,6 +1054,8 @@ eclkenable: | |||
976 | erate: | 1054 | erate: |
977 | clk_put(hdmi->hdmi_clk); | 1055 | clk_put(hdmi->hdmi_clk); |
978 | egetclk: | 1056 | egetclk: |
1057 | snd_soc_unregister_codec(&pdev->dev); | ||
1058 | esndreg: | ||
979 | kfree(hdmi); | 1059 | kfree(hdmi); |
980 | 1060 | ||
981 | return ret; | 1061 | return ret; |
@@ -988,6 +1068,8 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev) | |||
988 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1068 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
989 | int irq = platform_get_irq(pdev, 0); | 1069 | int irq = platform_get_irq(pdev, 0); |
990 | 1070 | ||
1071 | snd_soc_unregister_codec(&pdev->dev); | ||
1072 | |||
991 | pdata->lcd_chan->board_cfg.display_on = NULL; | 1073 | pdata->lcd_chan->board_cfg.display_on = NULL; |
992 | pdata->lcd_chan->board_cfg.display_off = NULL; | 1074 | pdata->lcd_chan->board_cfg.display_off = NULL; |
993 | pdata->lcd_chan->board_cfg.board_data = NULL; | 1075 | pdata->lcd_chan->board_cfg.board_data = NULL; |