1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2018 Rockchip Electronics Co., Ltd 4 */ 5 6 #include <dm.h> 7 #include <malloc.h> 8 #include <common.h> 9 #include <asm/io.h> 10 #include <linux/libfdt.h> 11 #include <fdtdec.h> 12 #include <i2s.h> 13 #include <sound.h> 14 #include <asm/arch-rockchip/resource_img.h> 15 16 #define WAV_SIZE (5 * 1024 * 1024) /* BYTE */ 17 #define SAMPLERATE 44100 18 19 static struct udevice *i2s_dev, *codec_dev; 20 21 static int load_audio_wav(void *buf, const char *wav_name, int size) 22 { 23 int ret = 0; 24 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE 25 ret = rockchip_read_resource_file(buf, wav_name, 0, size); 26 #endif 27 28 return ret; 29 } 30 31 static int sound_hw_params(struct udevice *dev, unsigned int samplerate, 32 unsigned int fmt, unsigned int channels) 33 { 34 const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev); 35 36 if (!ops || !ops->hw_params) 37 return -ENOTSUPP; 38 39 return ops->hw_params(dev, samplerate, fmt, channels); 40 } 41 42 static int sound_startup(struct udevice *dev) 43 { 44 const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev); 45 46 if (!ops || !ops->startup) 47 return -ENOTSUPP; 48 49 return ops->startup(dev); 50 } 51 52 static int sound_set_sysclk(struct udevice *dev, unsigned int freq) 53 { 54 const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev); 55 56 if (!ops || !ops->set_sysclk) 57 return -ENOTSUPP; 58 59 return ops->set_sysclk(dev, freq); 60 } 61 62 int sound_init(const void *blob) 63 { 64 int ret; 65 66 ret = uclass_get_device(UCLASS_I2S, 0, &i2s_dev); 67 if (ret) { 68 if (ret != -ENODEV) { 69 printf("Get i2s device failed: %d\n", ret); 70 return ret; 71 } 72 return 0; 73 } 74 75 ret = uclass_get_device(UCLASS_CODEC, 0, &codec_dev); 76 if (ret) { 77 if (ret != -ENODEV) { 78 printf("Get codec device failed: %d\n", ret); 79 return ret; 80 } 81 return 0; 82 } 83 84 sound_set_sysclk(i2s_dev, SAMPLERATE * 256); 85 sound_hw_params(i2s_dev, SAMPLERATE, 16, 2); 86 sound_hw_params(codec_dev, SAMPLERATE, 16, 2); 87 sound_startup(i2s_dev); 88 sound_startup(codec_dev); 89 90 return ret; 91 } 92 93 static int _sound_play(struct udevice *dev, unsigned int *data, 94 unsigned long data_size) 95 { 96 const struct snd_soc_dai_ops *ops = dev_get_driver_ops(dev); 97 98 if (!ops || !ops->transfer) 99 return -ENOTSUPP; 100 101 return ops->transfer(dev, data, data_size); 102 } 103 104 int sound_play(u32 msec, u32 frequency) 105 { 106 unsigned int *buf; 107 unsigned long buf_size; 108 unsigned int ret = 0; 109 110 buf_size = WAV_SIZE; 111 112 buf = malloc(buf_size); 113 if (!buf) { 114 debug("%s: buf malloc failed\n", __func__); 115 return -ENOMEM; 116 } 117 ret = load_audio_wav(buf, "boot.wav", buf_size); 118 /* if boot.wav not find, use sound_create_square_wave */ 119 if (ret <= 0) 120 sound_create_square_wave((unsigned short *)buf, 121 buf_size / sizeof(unsigned short), 122 frequency); 123 124 ret = _sound_play(i2s_dev, buf, (buf_size / sizeof(int))); 125 free(buf); 126 127 return ret; 128 } 129