1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "sherlock.h"
6 
7 #include <ddk/debug.h>
8 #include <ddk/device.h>
9 #include <ddk/platform-defs.h>
10 
11 #include <soc/aml-s905d2/s905d2-hiu.h>
12 #include <soc/aml-t931/t931-gpio.h>
13 #include <soc/aml-t931/t931-hw.h>
14 
15 namespace sherlock {
16 
AudioInit()17 zx_status_t Sherlock::AudioInit() {
18 
19     static constexpr pbus_gpio_t audio_gpios[] = {
20         {
21             // AUDIO_SOC_FAULT_L
22             .gpio = T931_GPIOZ(8),
23         },
24         {
25             // SOC_AUDIO_EN
26             .gpio = T931_GPIOH(7),
27         },
28     };
29 
30     static constexpr pbus_mmio_t audio_mmios[] = {
31         {
32             .base = T931_EE_AUDIO_BASE,
33             .length = T931_EE_AUDIO_LENGTH
34         },
35         {
36             .base = T931_GPIO_BASE,
37             .length = T931_GPIO_LENGTH,
38         },
39         {
40             .base = T931_GPIO_A0_BASE,
41             .length = T931_GPIO_AO_LENGTH,
42         },
43     };
44 
45     static constexpr pbus_bti_t tdm_btis[] = {
46         {
47             .iommu_index = 0,
48             .bti_id = BTI_AUDIO_OUT,
49         },
50     };
51 
52     static constexpr pbus_i2c_channel_t codecs_i2cs[] = {
53         {
54             .bus_id = SHERLOCK_I2C_A0_0,
55             .address = 0x6c, // Tweeters.
56         },
57         {
58             .bus_id = SHERLOCK_I2C_A0_0,
59             .address = 0x6f, // Woofer.
60         },
61     };
62 
63     pbus_dev_t tdm_dev = {};
64     tdm_dev.name = "SherlockAudio";
65     tdm_dev.vid = PDEV_VID_AMLOGIC;
66     tdm_dev.pid = PDEV_PID_AMLOGIC_T931;
67     tdm_dev.did = PDEV_DID_AMLOGIC_TDM;
68     tdm_dev.gpio_list = audio_gpios;
69     tdm_dev.gpio_count = countof(audio_gpios);
70     tdm_dev.i2c_channel_list = codecs_i2cs;
71     tdm_dev.i2c_channel_count = countof(codecs_i2cs);
72     tdm_dev.mmio_list = audio_mmios;
73     tdm_dev.mmio_count = countof(audio_mmios);
74     tdm_dev.bti_list = tdm_btis;
75     tdm_dev.bti_count = countof(tdm_btis);
76 
77 
78     static constexpr pbus_mmio_t pdm_mmios[] = {
79         {
80             .base = T931_EE_PDM_BASE,
81             .length = T931_EE_PDM_LENGTH
82         },
83         {
84             .base = T931_EE_AUDIO_BASE,
85             .length = T931_EE_AUDIO_LENGTH
86         },
87     };
88 
89     static constexpr pbus_bti_t pdm_btis[] = {
90         {
91             .iommu_index = 0,
92             .bti_id = BTI_AUDIO_IN,
93         },
94     };
95 
96     pbus_dev_t pdm_dev;
97     pdm_dev.name = "SherlockAudioIn";
98     pdm_dev.vid = PDEV_VID_AMLOGIC;
99     pdm_dev.pid = PDEV_PID_AMLOGIC_T931;
100     pdm_dev.did = PDEV_DID_SHERLOCK_PDM;
101     pdm_dev.mmio_list = pdm_mmios;
102     pdm_dev.mmio_count = countof(pdm_mmios);
103     pdm_dev.bti_list = pdm_btis;
104     pdm_dev.bti_count = countof(pdm_btis);
105 
106 
107     aml_hiu_dev_t hiu;
108     zx_status_t status = s905d2_hiu_init(&hiu);
109     if (status != ZX_OK) {
110         zxlogf(ERROR, "hiu_init: failed: %d\n", status);
111         return status;
112     }
113 
114     aml_pll_dev_t hifi_pll;
115     s905d2_pll_init(&hiu, &hifi_pll, HIFI_PLL);
116     status = s905d2_pll_set_rate(&hifi_pll, T931_HIFI_PLL_RATE);
117     if (status != ZX_OK) {
118         zxlogf(ERROR, "Invalid rate selected for hifipll\n");
119         return status;
120     }
121 
122     s905d2_pll_ena(&hifi_pll);
123 
124     // TDM pin assignments.
125     gpio_impl_.SetAltFunction(T931_GPIOZ(7), T931_GPIOZ_7_TDMC_SCLK_FN);
126     gpio_impl_.SetAltFunction(T931_GPIOZ(6), T931_GPIOZ_6_TDMC_FS_FN);
127     gpio_impl_.SetAltFunction(T931_GPIOZ(2), T931_GPIOZ_2_TDMC_D0_FN);
128     gpio_impl_.SetAltFunction(T931_GPIOZ(3), T931_GPIOZ_3_TDMC_D1_FN);
129     gpio_impl_.SetAltFunction(T931_GPIOAO(9), T931_GPIOAO_9_MCLK_FN);
130 
131     // PDM pin assignments.
132     gpio_impl_.SetAltFunction(T931_GPIOA(7), T931_GPIOA_7_PDM_DCLK_FN);
133     gpio_impl_.SetAltFunction(T931_GPIOA(8), T931_GPIOA_8_PDM_DIN0_FN);
134     gpio_impl_.SetAltFunction(T931_GPIOA(9), T931_GPIOA_9_PDM_DIN1_FN);
135 
136     gpio_impl_.ConfigOut(T931_GPIOH(7), 1); // SOC_AUDIO_EN.
137 
138     status = pbus_.DeviceAdd(&tdm_dev);
139     if (status != ZX_OK) {
140         zxlogf(ERROR, "%s pbus_.DeviceAdd failed %d\n", __FUNCTION__, status);
141         return status;
142     }
143     status = pbus_.DeviceAdd(&pdm_dev);
144     if (status != ZX_OK) {
145         zxlogf(ERROR, "%s pbus_.DeviceAdd failed %d\n", __FUNCTION__, status);
146         return status;
147     }
148     return ZX_OK;
149 }
150 
151 } // namespace sherlock
152