Unified · Split
| @@ -163,8 +163,71 @@ · 162 unmodified lines | |||
| 163 | * | 163 | * |
| 164 | * %SKL_TKN_U32_DMA_BUF_SIZE: DMA buffer size in millisec | 164 | * %SKL_TKN_U32_DMA_BUF_SIZE: DMA buffer size in millisec |
| 165 | * | 165 | * |
| 166 | * %SKL_TKN_U32_PIPE_DIR: Specifies pipe direction. Can be | ||
| 167 | * playback/capture. | ||
| 168 | * | ||
| 169 | * %SKL_TKN_U32_NUM_CONFIGS: Number of pipe configs | ||
| 170 | * | ||
| 171 | * %SKL_TKN_U32_PATH_MEM_PGS: Size of memory (in pages) required for pipeline | ||
| 172 | * and its data | ||
| 173 | * | ||
| 174 | * %SKL_TKN_U32_PIPE_CONFIG_ID: Config id for the modules in the pipe | ||
| 175 | * and PCM params supported by that pipe | ||
| 176 | * config. This is used as index to fill | ||
| 177 | * up the pipe config and module config | ||
| 178 | * structure. | ||
| 179 | * | ||
| 180 | * %SKL_TKN_U32_CFG_FREQ: | ||
| 181 | * %SKL_TKN_U8_CFG_CHAN: | ||
| 182 | * %SKL_TKN_U8_CFG_BPS: PCM params (freq, channels, bits per sample) | ||
| 183 | * supported for each of the pipe configs. | ||
| 184 | * | ||
| 185 | * %SKL_TKN_CFG_MOD_RES_ID: Module's resource index for each of the | ||
| 186 | * pipe config | ||
| 187 | * | ||
| 188 | * %SKL_TKN_CFG_MOD_FMT_ID: Module's interface index for each of the | ||
| 189 | * pipe config | ||
| 190 | * | ||
| 191 | * %SKL_TKN_U8_NUM_MOD: Number of modules in the manifest | ||
| 192 | * | ||
| 193 | * %SKL_TKN_MM_U8_MOD_IDX: Current index of the module in the manifest | ||
| 194 | * | ||
| 195 | * %SKL_TKN_MM_U8_NUM_RES: Number of resources for the module | ||
| 196 | * | ||
| 197 | * %SKL_TKN_MM_U8_NUM_INTF: Number of interfaces for the module | ||
| 198 | * | ||
| 199 | * %SKL_TKN_MM_U32_RES_ID: Resource index for the resource info to | ||
| 200 | * be filled into. | ||
| 201 | * A module can support multiple resource | ||
| 202 | * configuration and is represnted as a | ||
| 203 | * resource table. This index is used to | ||
| 204 | * fill information into appropriate index. | ||
| 205 | * | ||
| 206 | * %SKL_TKN_MM_U32_CPS: DSP cycles per second | ||
| 207 | * | ||
| 208 | * %SKL_TKN_MM_U32_DMA_SIZE: Allocated buffer size for gateway DMA | ||
| 209 | * | ||
| 210 | * %SKL_TKN_MM_U32_CPC: DSP cycles allocated per frame | ||
| 211 | * | ||
| 212 | * %SKL_TKN_MM_U32_RES_PIN_ID: Resource pin index in the module | ||
| 213 | * | ||
| 214 | * %SKL_TKN_MM_U32_INTF_PIN_ID: Interface index in the module | ||
| 215 | * | ||
| 216 | * %SKL_TKN_MM_U32_PIN_BUF: Buffer size of the module pin | ||
| 217 | * | ||
| 218 | * %SKL_TKN_MM_U32_FMT_ID: Format index for each of the interface/ | ||
| 219 | * format information to be filled into. | ||
| 220 | * | ||
| 221 | * %SKL_TKN_MM_U32_NUM_IN_FMT: Number of input formats | ||
| 222 | * %SKL_TKN_MM_U32_NUM_OUT_FMT: Number of output formats | ||
| 223 | * | ||
| 166 | * module_id and loadable flags dont have tokens as these values will be | 224 | * module_id and loadable flags dont have tokens as these values will be |
| 167 | * read from the DSP FW manifest | 225 | * read from the DSP FW manifest |
| 226 | * | ||
| 227 | * Tokens defined can be used either in the manifest or widget private data. | ||
| 228 | * | ||
| 229 | * SKL_TKN_MM is used as a suffix for all tokens that represent | ||
| 230 | * module data in the manifest. | ||
| 168 | */ | 231 | */ |
| 169 | enum SKL_TKNS { | 232 | enum SKL_TKNS { |
| 170 | SKL_TKN_UUID = 1, | 233 | SKL_TKN_UUID = 1, |
| @@ -218,7 +281,34 @@ enum SKL_TKNS { · 47 unmodified lines | |||
| 218 | SKL_TKL_U32_D0I3_CAPS, /* Typo added at v4.10 */ | 281 | SKL_TKL_U32_D0I3_CAPS, /* Typo added at v4.10 */ |
| 219 | SKL_TKN_U32_D0I3_CAPS = SKL_TKL_U32_D0I3_CAPS, | 282 | SKL_TKN_U32_D0I3_CAPS = SKL_TKL_U32_D0I3_CAPS, |
| 220 | SKL_TKN_U32_DMA_BUF_SIZE, | 283 | SKL_TKN_U32_DMA_BUF_SIZE, |
| 221 | SKL_TKN_MAX = SKL_TKN_U32_DMA_BUF_SIZE, | 284 | |
| 285 | SKL_TKN_U32_PIPE_DIRECTION, | ||
| 286 | SKL_TKN_U32_PIPE_CONFIG_ID, | ||
| 287 | SKL_TKN_U32_NUM_CONFIGS, | ||
| 288 | SKL_TKN_U32_PATH_MEM_PGS, | ||
| 289 | |||
| 290 | SKL_TKN_U32_CFG_FREQ, | ||
| 291 | SKL_TKN_U8_CFG_CHAN, | ||
| 292 | SKL_TKN_U8_CFG_BPS, | ||
| 293 | SKL_TKN_CFG_MOD_RES_ID, | ||
| 294 | SKL_TKN_CFG_MOD_FMT_ID, | ||
| 295 | SKL_TKN_U8_NUM_MOD, | ||
| 296 | |||
| 297 | SKL_TKN_MM_U8_MOD_IDX, | ||
| 298 | SKL_TKN_MM_U8_NUM_RES, | ||
| 299 | SKL_TKN_MM_U8_NUM_INTF, | ||
| 300 | SKL_TKN_MM_U32_RES_ID, | ||
| 301 | SKL_TKN_MM_U32_CPS, | ||
| 302 | SKL_TKN_MM_U32_DMA_SIZE, | ||
| 303 | SKL_TKN_MM_U32_CPC, | ||
| 304 | SKL_TKN_MM_U32_RES_PIN_ID, | ||
| 305 | SKL_TKN_MM_U32_INTF_PIN_ID, | ||
| 306 | SKL_TKN_MM_U32_PIN_BUF, | ||
| 307 | SKL_TKN_MM_U32_FMT_ID, | ||
| 308 | SKL_TKN_MM_U32_NUM_IN_FMT, | ||
| 309 | SKL_TKN_MM_U32_NUM_OUT_FMT, | ||
| 310 | |||
| 311 | SKL_TKN_MAX = SKL_TKN_MM_U32_NUM_OUT_FMT, | ||
| 222 | }; | 312 | }; |
| 223 | 313 | ||
| 224 | #endif | 314 | #endif |
| @@ -321,6 +321,7 @@ obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o · 320 unmodified lines | |||
| 321 | obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o | 321 | obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o |
| 322 | obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o | 322 | obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o |
| 323 | obj-$(CONFIG_SND_SOC_MAX98357A) += snd-soc-max98357a.o | 323 | obj-$(CONFIG_SND_SOC_MAX98357A) += snd-soc-max98357a.o |
| 324 | obj-$(CONFIG_SND_SOC_MAX98371) += snd-soc-max98371.o | ||
| 324 | obj-$(CONFIG_SND_SOC_MAX9867) += snd-soc-max9867.o | 325 | obj-$(CONFIG_SND_SOC_MAX9867) += snd-soc-max9867.o |
| 325 | obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o | 326 | obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o |
| 326 | obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o | 327 | obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o |
| @@ -121,6 +121,10 @@ struct hdac_hdmi_dai_port_map { · 120 unmodified lines | |||
| 121 | struct hdac_hdmi_cvt *cvt; | 121 | struct hdac_hdmi_cvt *cvt; |
| 122 | }; | 122 | }; |
| 123 | 123 | ||
| 124 | struct hdac_hdmi_drv_data { | ||
| 125 | unsigned int vendor_nid; | ||
| 126 | }; | ||
| 127 | |||
| 124 | struct hdac_hdmi_priv { | 128 | struct hdac_hdmi_priv { |
| 125 | struct hdac_hdmi_dai_port_map dai_map[HDA_MAX_CVTS]; | 129 | struct hdac_hdmi_dai_port_map dai_map[HDA_MAX_CVTS]; |
| 126 | struct list_head pin_list; | 130 | struct list_head pin_list; |
| @@ -131,6 +135,7 @@ struct hdac_hdmi_priv { · 4 unmodified lines | |||
| 131 | int num_ports; | 135 | int num_ports; |
| 132 | struct mutex pin_mutex; | 136 | struct mutex pin_mutex; |
| 133 | struct hdac_chmap chmap; | 137 | struct hdac_chmap chmap; |
| 138 | struct hdac_hdmi_drv_data *drv_data; | ||
| 134 | }; | 139 | }; |
| 135 | 140 | ||
| 136 | static struct hdac_hdmi_pcm * | 141 | static struct hdac_hdmi_pcm * |
| @@ -1321,6 +1326,7 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) · 1184 unmodified lines | |||
| 1321 | } | 1326 | } |
| 1322 | 1327 | ||
| 1323 | #define INTEL_VENDOR_NID 0x08 | 1328 | #define INTEL_VENDOR_NID 0x08 |
| 1329 | #define INTEL_GLK_VENDOR_NID 0x0b | ||
| 1324 | #define INTEL_GET_VENDOR_VERB 0xf81 | 1330 | #define INTEL_GET_VENDOR_VERB 0xf81 |
| 1325 | #define INTEL_SET_VENDOR_VERB 0x781 | 1331 | #define INTEL_SET_VENDOR_VERB 0x781 |
| 1326 | #define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */ | 1332 | #define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */ |
| @@ -1329,14 +1335,17 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) · 2 unmodified lines | |||
| 1329 | static void hdac_hdmi_skl_enable_all_pins(struct hdac_device *hdac) | 1335 | static void hdac_hdmi_skl_enable_all_pins(struct hdac_device *hdac) |
| 1330 | { | 1336 | { |
| 1331 | unsigned int vendor_param; | 1337 | unsigned int vendor_param; |
| 1338 | struct hdac_ext_device *edev = to_ehdac_device(hdac); | ||
| 1339 | struct hdac_hdmi_priv *hdmi = edev->private_data; | ||
| 1340 | unsigned int vendor_nid = hdmi->drv_data->vendor_nid; | ||
| 1332 | 1341 | ||
| 1333 | vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0, | 1342 | vendor_param = snd_hdac_codec_read(hdac, vendor_nid, 0, |
| 1334 | INTEL_GET_VENDOR_VERB, 0); | 1343 | INTEL_GET_VENDOR_VERB, 0); |
| 1335 | if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS) | 1344 | if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS) |
| 1336 | return; | 1345 | return; |
| 1337 | 1346 | ||
| 1338 | vendor_param |= INTEL_EN_ALL_PIN_CVTS; | 1347 | vendor_param |= INTEL_EN_ALL_PIN_CVTS; |
| 1339 | vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0, | 1348 | vendor_param = snd_hdac_codec_read(hdac, vendor_nid, 0, |
| 1340 | INTEL_SET_VENDOR_VERB, vendor_param); | 1349 | INTEL_SET_VENDOR_VERB, vendor_param); |
| 1341 | if (vendor_param == -1) | 1350 | if (vendor_param == -1) |
| 1342 | return; | 1351 | return; |
| @@ -1345,15 +1354,18 @@ static void hdac_hdmi_skl_enable_all_pins(struct hdac_device *hdac) · 2 unmodified lines | |||
| 1345 | static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac) | 1354 | static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac) |
| 1346 | { | 1355 | { |
| 1347 | unsigned int vendor_param; | 1356 | unsigned int vendor_param; |
| 1357 | struct hdac_ext_device *edev = to_ehdac_device(hdac); | ||
| 1358 | struct hdac_hdmi_priv *hdmi = edev->private_data; | ||
| 1359 | unsigned int vendor_nid = hdmi->drv_data->vendor_nid; | ||
| 1348 | 1360 | ||
| 1349 | vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0, | 1361 | vendor_param = snd_hdac_codec_read(hdac, vendor_nid, 0, |
| 1350 | INTEL_GET_VENDOR_VERB, 0); | 1362 | INTEL_GET_VENDOR_VERB, 0); |
| 1351 | if (vendor_param == -1 || vendor_param & INTEL_EN_DP12) | 1363 | if (vendor_param == -1 || vendor_param & INTEL_EN_DP12) |
| 1352 | return; | 1364 | return; |
| 1353 | 1365 | ||
| 1354 | /* enable DP1.2 mode */ | 1366 | /* enable DP1.2 mode */ |
| 1355 | vendor_param |= INTEL_EN_DP12; | 1367 | vendor_param |= INTEL_EN_DP12; |
| 1356 | vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0, | 1368 | vendor_param = snd_hdac_codec_read(hdac, vendor_nid, 0, |
| 1357 | INTEL_SET_VENDOR_VERB, vendor_param); | 1369 | INTEL_SET_VENDOR_VERB, vendor_param); |
| 1358 | if (vendor_param == -1) | 1370 | if (vendor_param == -1) |
| 1359 | return; | 1371 | return; |
| @@ -1927,6 +1939,14 @@ static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx) · 567 unmodified lines | |||
| 1927 | return port->eld.info.spk_alloc; | 1939 | return port->eld.info.spk_alloc; |
| 1928 | } | 1940 | } |
| 1929 | 1941 | ||
| 1942 | static struct hdac_hdmi_drv_data intel_glk_drv_data = { | ||
| 1943 | .vendor_nid = INTEL_GLK_VENDOR_NID, | ||
| 1944 | }; | ||
| 1945 | |||
| 1946 | static struct hdac_hdmi_drv_data intel_drv_data = { | ||
| 1947 | .vendor_nid = INTEL_VENDOR_NID, | ||
| 1948 | }; | ||
| 1949 | |||
| 1930 | static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) | 1950 | static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) |
| 1931 | { | 1951 | { |
| 1932 | struct hdac_device *codec = &edev->hdac; | 1952 | struct hdac_device *codec = &edev->hdac; |
| @@ -1935,6 +1955,8 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) · 2 unmodified lines | |||
| 1935 | struct hdac_ext_link *hlink = NULL; | 1955 | struct hdac_ext_link *hlink = NULL; |
| 1936 | int num_dais = 0; | 1956 | int num_dais = 0; |
| 1937 | int ret = 0; | 1957 | int ret = 0; |
| 1958 | struct hdac_driver *hdrv = drv_to_hdac_driver(codec->dev.driver); | ||
| 1959 | const struct hda_device_id *hdac_id = hdac_get_device_id(codec, hdrv); | ||
| 1938 | 1960 | ||
| 1939 | /* hold the ref while we probe */ | 1961 | /* hold the ref while we probe */ |
| 1940 | hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdac.dev)); | 1962 | hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdac.dev)); |
| @@ -1956,6 +1978,12 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) · 15 unmodified lines | |||
| 1956 | hdmi_priv->chmap.ops.is_pcm_attached = is_hdac_hdmi_pcm_attached; | 1978 | hdmi_priv->chmap.ops.is_pcm_attached = is_hdac_hdmi_pcm_attached; |
| 1957 | hdmi_priv->chmap.ops.get_spk_alloc = hdac_hdmi_get_spk_alloc; | 1979 | hdmi_priv->chmap.ops.get_spk_alloc = hdac_hdmi_get_spk_alloc; |
| 1958 | 1980 | ||
| 1981 | if (hdac_id->driver_data) | ||
| 1982 | hdmi_priv->drv_data = | ||
| 1983 | (struct hdac_hdmi_drv_data *)hdac_id->driver_data; | ||
| 1984 | else | ||
| 1985 | hdmi_priv->drv_data = &intel_drv_data; | ||
| 1986 | |||
| 1959 | dev_set_drvdata(&codec->dev, edev); | 1987 | dev_set_drvdata(&codec->dev, edev); |
| 1960 | 1988 | ||
| 1961 | INIT_LIST_HEAD(&hdmi_priv->pin_list); | 1989 | INIT_LIST_HEAD(&hdmi_priv->pin_list); |
| @@ -2127,7 +2155,8 @@ static const struct hda_device_id hdmi_list[] = { · 165 unmodified lines | |||
| 2127 | HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0), | 2155 | HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0), |
| 2128 | HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0), | 2156 | HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0), |
| 2129 | HDA_CODEC_EXT_ENTRY(0x8086280b, 0x100000, "Kabylake HDMI", 0), | 2157 | HDA_CODEC_EXT_ENTRY(0x8086280b, 0x100000, "Kabylake HDMI", 0), |
| 2130 | HDA_CODEC_EXT_ENTRY(0x8086280d, 0x100000, "Geminilake HDMI", 0), | 2158 | HDA_CODEC_EXT_ENTRY(0x8086280d, 0x100000, "Geminilake HDMI", |
| 2159 | &intel_glk_drv_data), | ||
| 2131 | {} | 2160 | {} |
| 2132 | }; | 2161 | }; |
| 2133 | 2162 | ||
| @@ -349,12 +349,14 @@ static struct snd_soc_dai_driver max98371_dai[] = { · 348 unmodified lines | |||
| 349 | }; | 349 | }; |
| 350 | 350 | ||
| 351 | static const struct snd_soc_codec_driver max98371_codec = { | 351 | static const struct snd_soc_codec_driver max98371_codec = { |
| 352 | .controls = max98371_snd_controls, | 352 | .component_driver = { |
| 353 | .num_controls = ARRAY_SIZE(max98371_snd_controls), | 353 | .controls = max98371_snd_controls, |
| 354 | .dapm_routes = max98371_audio_map, | 354 | .num_controls = ARRAY_SIZE(max98371_snd_controls), |
| 355 | .num_dapm_routes = ARRAY_SIZE(max98371_audio_map), | 355 | .dapm_routes = max98371_audio_map, |
| 356 | .dapm_widgets = max98371_dapm_widgets, | 356 | .num_dapm_routes = ARRAY_SIZE(max98371_audio_map), |
| 357 | .num_dapm_widgets = ARRAY_SIZE(max98371_dapm_widgets), | 357 | .dapm_widgets = max98371_dapm_widgets, |
| 358 | .num_dapm_widgets = ARRAY_SIZE(max98371_dapm_widgets), | ||
| 359 | }, | ||
| 358 | }; | 360 | }; |
| 359 | 361 | ||
| 360 | static const struct regmap_config max98371_regmap = { | 362 | static const struct regmap_config max98371_regmap = { |
| @@ -255,11 +255,12 @@ config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH · 254 unmodified lines | |||
| 255 | 255 | ||
| 256 | config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH | 256 | config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH |
| 257 | tristate "ASoC Audio driver for KBL with RT5663, RT5514 and MAX98927 in I2S Mode" | 257 | tristate "ASoC Audio driver for KBL with RT5663, RT5514 and MAX98927 in I2S Mode" |
| 258 | depends on X86_INTEL_LPSS && I2C | 258 | depends on X86_INTEL_LPSS && I2C && SPI |
| 259 | select SND_SOC_INTEL_SST | 259 | select SND_SOC_INTEL_SST |
| 260 | select SND_SOC_INTEL_SKYLAKE | 260 | select SND_SOC_INTEL_SKYLAKE |
| 261 | select SND_SOC_RT5663 | 261 | select SND_SOC_RT5663 |
| 262 | select SND_SOC_RT5514 | 262 | select SND_SOC_RT5514 |
| 263 | select SND_SOC_RT5514_SPI | ||
| 263 | select SND_SOC_MAX98927 | 264 | select SND_SOC_MAX98927 |
| 264 | select SND_SOC_HDAC_HDMI | 265 | select SND_SOC_HDAC_HDMI |
| 265 | help | 266 | help |
| @@ -76,7 +76,7 @@ int sst_unregister_dsp(struct sst_device *dev) · 75 unmodified lines | |||
| 76 | } | 76 | } |
| 77 | EXPORT_SYMBOL_GPL(sst_unregister_dsp); | 77 | EXPORT_SYMBOL_GPL(sst_unregister_dsp); |
| 78 | 78 | ||
| 79 | static struct snd_pcm_hardware sst_platform_pcm_hw = { | 79 | static const struct snd_pcm_hardware sst_platform_pcm_hw = { |
| 80 | .info = (SNDRV_PCM_INFO_INTERLEAVED | | 80 | .info = (SNDRV_PCM_INFO_INTERLEAVED | |
| 81 | SNDRV_PCM_INFO_DOUBLE | | 81 | SNDRV_PCM_INFO_DOUBLE | |
| 82 | SNDRV_PCM_INFO_PAUSE | | 82 | SNDRV_PCM_INFO_PAUSE | |
| @@ -471,7 +471,7 @@ static void sst_disable_ssp(struct snd_pcm_substream *substream, · 388 unmodified lines | |||
| 471 | } | 471 | } |
| 472 | } | 472 | } |
| 473 | 473 | ||
| 474 | static struct snd_soc_dai_ops sst_media_dai_ops = { | 474 | static const struct snd_soc_dai_ops sst_media_dai_ops = { |
| 475 | .startup = sst_media_open, | 475 | .startup = sst_media_open, |
| 476 | .shutdown = sst_media_close, | 476 | .shutdown = sst_media_close, |
| 477 | .prepare = sst_media_prepare, | 477 | .prepare = sst_media_prepare, |
| @@ -480,11 +480,11 @@ static struct snd_soc_dai_ops sst_media_dai_ops = { · 2 unmodified lines | |||
| 480 | .mute_stream = sst_media_digital_mute, | 480 | .mute_stream = sst_media_digital_mute, |
| 481 | }; | 481 | }; |
| 482 | 482 | ||
| 483 | static struct snd_soc_dai_ops sst_compr_dai_ops = { | 483 | static const struct snd_soc_dai_ops sst_compr_dai_ops = { |
| 484 | .mute_stream = sst_media_digital_mute, | 484 | .mute_stream = sst_media_digital_mute, |
| 485 | }; | 485 | }; |
| 486 | 486 | ||
| 487 | static struct snd_soc_dai_ops sst_be_dai_ops = { | 487 | static const struct snd_soc_dai_ops sst_be_dai_ops = { |
| 488 | .startup = sst_enable_ssp, | 488 | .startup = sst_enable_ssp, |
| 489 | .hw_params = sst_be_hw_params, | 489 | .hw_params = sst_be_hw_params, |
| 490 | .set_fmt = sst_set_format, | 490 | .set_fmt = sst_set_format, |
| @@ -705,7 +705,7 @@ static int sst_soc_probe(struct snd_soc_platform *platform) · 214 unmodified lines | |||
| 705 | return sst_dsp_init_v2_dpcm(platform); | 705 | return sst_dsp_init_v2_dpcm(platform); |
| 706 | } | 706 | } |
| 707 | 707 | ||
| 708 | static struct snd_soc_platform_driver sst_soc_platform_drv = { | 708 | static const struct snd_soc_platform_driver sst_soc_platform_drv = { |
| 709 | .probe = sst_soc_probe, | 709 | .probe = sst_soc_probe, |
| 710 | .ops = &sst_platform_ops, | 710 | .ops = &sst_platform_ops, |
| 711 | .compr_ops = &sst_platform_compr_ops, | 711 | .compr_ops = &sst_platform_compr_ops, |
| @@ -407,7 +407,7 @@ static int sst_cdev_caps(struct snd_compr_caps *caps) · 406 unmodified lines | |||
| 407 | return 0; | 407 | return 0; |
| 408 | } | 408 | } |
| 409 | 409 | ||
| 410 | static struct snd_compr_codec_caps caps_mp3 = { | 410 | static const struct snd_compr_codec_caps caps_mp3 = { |
| 411 | .num_descriptors = 1, | 411 | .num_descriptors = 1, |
| 412 | .descriptor[0].max_ch = 2, | 412 | .descriptor[0].max_ch = 2, |
| 413 | .descriptor[0].sample_rates[0] = 48000, | 413 | .descriptor[0].sample_rates[0] = 48000, |
| @@ -424,7 +424,7 @@ static struct snd_compr_codec_caps caps_mp3 = { · 10 unmodified lines | |||
| 424 | .descriptor[0].formats = 0, | 424 | .descriptor[0].formats = 0, |
| 425 | }; | 425 | }; |
| 426 | 426 | ||
| 427 | static struct snd_compr_codec_caps caps_aac = { | 427 | static const struct snd_compr_codec_caps caps_aac = { |
| 428 | .num_descriptors = 2, | 428 | .num_descriptors = 2, |
| 429 | .descriptor[1].max_ch = 2, | 429 | .descriptor[1].max_ch = 2, |
| 430 | .descriptor[0].sample_rates[0] = 48000, | 430 | .descriptor[0].sample_rates[0] = 48000, |
| @@ -181,7 +181,7 @@ static void intel_sst_remove(struct pci_dev *pci) · 180 unmodified lines | |||
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | /* PCI Routines */ | 183 | /* PCI Routines */ |
| 184 | static struct pci_device_id intel_sst_ids[] = { | 184 | static const struct pci_device_id intel_sst_ids[] = { |
| 185 | { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0}, | 185 | { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0}, |
| 186 | { 0, } | 186 | { 0, } |
| 187 | }; | 187 | }; |
| @@ -309,7 +309,7 @@ static int sst_byt_pcm_mmap(struct snd_pcm_substream *substream, · 308 unmodified lines | |||
| 309 | return snd_pcm_lib_default_mmap(substream, vma); | 309 | return snd_pcm_lib_default_mmap(substream, vma); |
| 310 | } | 310 | } |
| 311 | 311 | ||
| 312 | static struct snd_pcm_ops sst_byt_pcm_ops = { | 312 | static const struct snd_pcm_ops sst_byt_pcm_ops = { |
| 313 | .open = sst_byt_pcm_open, | 313 | .open = sst_byt_pcm_open, |
| 314 | .close = sst_byt_pcm_close, | 314 | .close = sst_byt_pcm_close, |
| 315 | .ioctl = snd_pcm_lib_ioctl, | 315 | .ioctl = snd_pcm_lib_ioctl, |
| @@ -395,7 +395,7 @@ static int sst_byt_pcm_remove(struct snd_soc_platform *platform) · 79 unmodified lines | |||
| 395 | return 0; | 395 | return 0; |
| 396 | } | 396 | } |
| 397 | 397 | ||
| 398 | static struct snd_soc_platform_driver byt_soc_platform = { | 398 | static const struct snd_soc_platform_driver byt_soc_platform = { |
| 399 | .probe = sst_byt_pcm_probe, | 399 | .probe = sst_byt_pcm_probe, |
| 400 | .remove = sst_byt_pcm_remove, | 400 | .remove = sst_byt_pcm_remove, |
| 401 | .ops = &sst_byt_pcm_ops, | 401 | .ops = &sst_byt_pcm_ops, |
| @@ -114,7 +114,44 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = { · 113 unmodified lines | |||
| 114 | { "iDisp2 Tx", NULL, "iDisp2_out"}, | 114 | { "iDisp2 Tx", NULL, "iDisp2_out"}, |
| 115 | { "hifi1", NULL, "iDisp1 Tx"}, | 115 | { "hifi1", NULL, "iDisp1 Tx"}, |
| 116 | { "iDisp1 Tx", NULL, "iDisp1_out"}, | 116 | { "iDisp1 Tx", NULL, "iDisp1_out"}, |
| 117 | }; | ||
| 118 | |||
| 119 | static const struct snd_soc_dapm_route geminilake_rt298_map[] = { | ||
| 120 | /* speaker */ | ||
| 121 | {"Speaker", NULL, "SPOR"}, | ||
| 122 | {"Speaker", NULL, "SPOL"}, | ||
| 123 | |||
| 124 | /* HP jack connectors - unknown if we have jack detect */ | ||
| 125 | {"Headphone Jack", NULL, "HPO Pin"}, | ||
| 126 | |||
| 127 | /* other jacks */ | ||
| 128 | {"MIC1", NULL, "Mic Jack"}, | ||
| 129 | |||
| 130 | /* digital mics */ | ||
| 131 | {"DMIC1 Pin", NULL, "DMIC2"}, | ||
| 132 | {"DMic", NULL, "SoC DMIC"}, | ||
| 133 | |||
| 134 | {"HDMI1", NULL, "hif5-0 Output"}, | ||
| 135 | {"HDMI2", NULL, "hif6-0 Output"}, | ||
| 136 | {"HDMI2", NULL, "hif7-0 Output"}, | ||
| 137 | |||
| 138 | /* CODEC BE connections */ | ||
| 139 | { "AIF1 Playback", NULL, "ssp2 Tx"}, | ||
| 140 | { "ssp2 Tx", NULL, "codec0_out"}, | ||
| 141 | { "ssp2 Tx", NULL, "codec1_out"}, | ||
| 142 | |||
| 143 | { "codec0_in", NULL, "ssp2 Rx" }, | ||
| 144 | { "ssp2 Rx", NULL, "AIF1 Capture" }, | ||
| 117 | 145 | ||
| 146 | { "dmic01_hifi", NULL, "DMIC01 Rx" }, | ||
| 147 | { "DMIC01 Rx", NULL, "Capture" }, | ||
| 148 | |||
| 149 | { "hifi3", NULL, "iDisp3 Tx"}, | ||
| 150 | { "iDisp3 Tx", NULL, "iDisp3_out"}, | ||
| 151 | { "hifi2", NULL, "iDisp2 Tx"}, | ||
| 152 | { "iDisp2 Tx", NULL, "iDisp2_out"}, | ||
| 153 | { "hifi1", NULL, "iDisp1 Tx"}, | ||
| 154 | { "iDisp1 Tx", NULL, "iDisp1_out"}, | ||
| 118 | }; | 155 | }; |
| 119 | 156 | ||
| 120 | static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd) | 157 | static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd) |
| @@ -492,7 +529,6 @@ static int bxt_card_late_probe(struct snd_soc_card *card) · 371 unmodified lines | |||
| 492 | /* broxton audio machine driver for SPT + RT298S */ | 529 | /* broxton audio machine driver for SPT + RT298S */ |
| 493 | static struct snd_soc_card broxton_rt298 = { | 530 | static struct snd_soc_card broxton_rt298 = { |
| 494 | .name = "broxton-rt298", | 531 | .name = "broxton-rt298", |
| 495 | .owner = THIS_MODULE, | ||
| 496 | .dai_link = broxton_rt298_dais, | 532 | .dai_link = broxton_rt298_dais, |
| 497 | .num_links = ARRAY_SIZE(broxton_rt298_dais), | 533 | .num_links = ARRAY_SIZE(broxton_rt298_dais), |
| 498 | .controls = broxton_controls, | 534 | .controls = broxton_controls, |
| @@ -506,9 +542,41 @@ static struct snd_soc_card broxton_rt298 = { · 7 unmodified lines | |||
| 506 | 542 | ||
| 507 | }; | 543 | }; |
| 508 | 544 | ||
| 545 | static struct snd_soc_card geminilake_rt298 = { | ||
| 546 | .name = "geminilake-rt298", | ||
| 547 | .dai_link = broxton_rt298_dais, | ||
| 548 | .num_links = ARRAY_SIZE(broxton_rt298_dais), | ||
| 549 | .controls = broxton_controls, | ||
| 550 | .num_controls = ARRAY_SIZE(broxton_controls), | ||
| 551 | .dapm_widgets = broxton_widgets, | ||
| 552 | .num_dapm_widgets = ARRAY_SIZE(broxton_widgets), | ||
| 553 | .dapm_routes = geminilake_rt298_map, | ||
| 554 | .num_dapm_routes = ARRAY_SIZE(geminilake_rt298_map), | ||
| 555 | .fully_routed = true, | ||
| 556 | .late_probe = bxt_card_late_probe, | ||
| 557 | }; | ||
| 558 | |||
| 509 | static int broxton_audio_probe(struct platform_device *pdev) | 559 | static int broxton_audio_probe(struct platform_device *pdev) |
| 510 | { | 560 | { |
| 511 | struct bxt_rt286_private *ctx; | 561 | struct bxt_rt286_private *ctx; |
| 562 | struct snd_soc_card *card = | ||
| 563 | (struct snd_soc_card *)pdev->id_entry->driver_data; | ||
| 564 | int i; | ||
| 565 | |||
| 566 | for (i = 0; i < ARRAY_SIZE(broxton_rt298_dais); i++) { | ||
| 567 | if (!strncmp(card->dai_link[i].codec_name, "i2c-INT343A:00", | ||
| 568 | I2C_NAME_SIZE)) { | ||
| 569 | if (!strncmp(card->name, "broxton-rt298", | ||
| 570 | PLATFORM_NAME_SIZE)) { | ||
| 571 | card->dai_link[i].name = "SSP5-Codec"; | ||
| 572 | card->dai_link[i].cpu_dai_name = "SSP5 Pin"; | ||
| 573 | } else if (!strncmp(card->name, "geminilake-rt298", | ||
| 574 | PLATFORM_NAME_SIZE)) { | ||
| 575 | card->dai_link[i].name = "SSP2-Codec"; | ||
| 576 | card->dai_link[i].cpu_dai_name = "SSP2 Pin"; | ||
| 577 | } | ||
| 578 | } | ||
| 579 | } | ||
| 512 | 580 | ||
| 513 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); | 581 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); |
| 514 | if (!ctx) | 582 | if (!ctx) |
| @@ -516,18 +584,27 @@ static int broxton_audio_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 516 | 584 | ||
| 517 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); | 585 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); |
| 518 | 586 | ||
| 519 | broxton_rt298.dev = &pdev->dev; | 587 | card->dev = &pdev->dev; |
| 520 | snd_soc_card_set_drvdata(&broxton_rt298, ctx); | 588 | snd_soc_card_set_drvdata(card, ctx); |
| 521 | 589 | ||
| 522 | return devm_snd_soc_register_card(&pdev->dev, &broxton_rt298); | 590 | return devm_snd_soc_register_card(&pdev->dev, card); |
| 523 | } | 591 | } |
| 524 | 592 | ||
| 593 | static const struct platform_device_id bxt_board_ids[] = { | ||
| 594 | { .name = "bxt_alc298s_i2s", .driver_data = | ||
| 595 | (unsigned long)&broxton_rt298 }, | ||
| 596 | { .name = "glk_alc298s_i2s", .driver_data = | ||
| 597 | (unsigned long)&geminilake_rt298 }, | ||
| 598 | {} | ||
| 599 | }; | ||
| 600 | |||
| 525 | static struct platform_driver broxton_audio = { | 601 | static struct platform_driver broxton_audio = { |
| 526 | .probe = broxton_audio_probe, | 602 | .probe = broxton_audio_probe, |
| 527 | .driver = { | 603 | .driver = { |
| 528 | .name = "bxt_alc298s_i2s", | 604 | .name = "bxt_alc298s_i2s", |
| 529 | .pm = &snd_soc_pm_ops, | 605 | .pm = &snd_soc_pm_ops, |
| 530 | }, | 606 | }, |
| 607 | .id_table = bxt_board_ids, | ||
| 531 | }; | 608 | }; |
| 532 | module_platform_driver(broxton_audio) | 609 | module_platform_driver(broxton_audio) |
| 533 | 610 | ||
| @@ -537,3 +614,4 @@ MODULE_AUTHOR("Senthilnathan Veppur <senthilnathanx.veppur@intel.com>"); · 3 unmodified lines | |||
| 537 | MODULE_DESCRIPTION("Intel SST Audio for Broxton"); | 614 | MODULE_DESCRIPTION("Intel SST Audio for Broxton"); |
| 538 | MODULE_LICENSE("GPL v2"); | 615 | MODULE_LICENSE("GPL v2"); |
| 539 | MODULE_ALIAS("platform:bxt_alc298s_i2s"); | 616 | MODULE_ALIAS("platform:bxt_alc298s_i2s"); |
| 617 | MODULE_ALIAS("platform:glk_alc298s_i2s"); | ||
| @@ -34,7 +34,7 @@ · 33 unmodified lines | |||
| 34 | #define MAXIM_DEV0_NAME "i2c-MX98927:00" | 34 | #define MAXIM_DEV0_NAME "i2c-MX98927:00" |
| 35 | #define MAXIM_DEV1_NAME "i2c-MX98927:01" | 35 | #define MAXIM_DEV1_NAME "i2c-MX98927:01" |
| 36 | 36 | ||
| 37 | static struct snd_soc_card kabylake_audio_card; | 37 | static struct snd_soc_card *kabylake_audio_card; |
| 38 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; | 38 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; |
| 39 | static struct snd_soc_jack skylake_hdmi[3]; | 39 | static struct snd_soc_jack skylake_hdmi[3]; |
| 40 | 40 | ||
| @@ -52,6 +52,8 @@ struct kbl_rt5663_private { · 11 unmodified lines | |||
| 52 | enum { | 52 | enum { |
| 53 | KBL_DPCM_AUDIO_PB = 0, | 53 | KBL_DPCM_AUDIO_PB = 0, |
| 54 | KBL_DPCM_AUDIO_CP, | 54 | KBL_DPCM_AUDIO_CP, |
| 55 | KBL_DPCM_AUDIO_HS_PB, | ||
| 56 | KBL_DPCM_AUDIO_ECHO_REF_CP, | ||
| 55 | KBL_DPCM_AUDIO_REF_CP, | 57 | KBL_DPCM_AUDIO_REF_CP, |
| 56 | KBL_DPCM_AUDIO_DMIC_CP, | 58 | KBL_DPCM_AUDIO_DMIC_CP, |
| 57 | KBL_DPCM_AUDIO_HDMI1_PB, | 59 | KBL_DPCM_AUDIO_HDMI1_PB, |
| @@ -72,8 +74,9 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = { · 14 unmodified lines | |||
| 72 | SND_SOC_DAPM_SPK("Left Spk", NULL), | 74 | SND_SOC_DAPM_SPK("Left Spk", NULL), |
| 73 | SND_SOC_DAPM_SPK("Right Spk", NULL), | 75 | SND_SOC_DAPM_SPK("Right Spk", NULL), |
| 74 | SND_SOC_DAPM_MIC("SoC DMIC", NULL), | 76 | SND_SOC_DAPM_MIC("SoC DMIC", NULL), |
| 75 | SND_SOC_DAPM_SPK("DP", NULL), | 77 | SND_SOC_DAPM_SPK("HDMI1", NULL), |
| 76 | SND_SOC_DAPM_SPK("HDMI", NULL), | 78 | SND_SOC_DAPM_SPK("HDMI2", NULL), |
| 79 | SND_SOC_DAPM_SPK("HDMI3", NULL), | ||
| 77 | 80 | ||
| 78 | }; | 81 | }; |
| 79 | 82 | ||
| @@ -91,20 +94,22 @@ static const struct snd_soc_dapm_route kabylake_map[] = { · 11 unmodified lines | |||
| 91 | { "IN1N", NULL, "Headset Mic" }, | 94 | { "IN1N", NULL, "Headset Mic" }, |
| 92 | { "DMic", NULL, "SoC DMIC" }, | 95 | { "DMic", NULL, "SoC DMIC" }, |
| 93 | 96 | ||
| 94 | { "HDMI", NULL, "hif5 Output" }, | ||
| 95 | { "DP", NULL, "hif6 Output" }, | ||
| 96 | |||
| 97 | /* CODEC BE connections */ | 97 | /* CODEC BE connections */ |
| 98 | { "Left HiFi Playback", NULL, "ssp0 Tx" }, | 98 | { "Left HiFi Playback", NULL, "ssp0 Tx" }, |
| 99 | { "Right HiFi Playback", NULL, "ssp0 Tx" }, | 99 | { "Right HiFi Playback", NULL, "ssp0 Tx" }, |
| 100 | { "ssp0 Tx", NULL, "codec0_out" }, | 100 | { "ssp0 Tx", NULL, "spk_out" }, |
| 101 | 101 | ||
| 102 | { "AIF Playback", NULL, "ssp1 Tx" }, | 102 | { "AIF Playback", NULL, "ssp1 Tx" }, |
| 103 | { "ssp1 Tx", NULL, "codec1_out" }, | 103 | { "ssp1 Tx", NULL, "hs_out" }, |
| 104 | 104 | ||
| 105 | { "codec0_in", NULL, "ssp1 Rx" }, | 105 | { "hs_in", NULL, "ssp1 Rx" }, |
| 106 | { "ssp1 Rx", NULL, "AIF Capture" }, | 106 | { "ssp1 Rx", NULL, "AIF Capture" }, |
| 107 | 107 | ||
| 108 | /* IV feedback path */ | ||
| 109 | { "codec0_fb_in", NULL, "ssp0 Rx"}, | ||
| 110 | { "ssp0 Rx", NULL, "Left HiFi Capture" }, | ||
| 111 | { "ssp0 Rx", NULL, "Right HiFi Capture" }, | ||
| 112 | |||
| 108 | /* DMIC */ | 113 | /* DMIC */ |
| 109 | { "dmic01_hifi", NULL, "DMIC01 Rx" }, | 114 | { "dmic01_hifi", NULL, "DMIC01 Rx" }, |
| 110 | { "DMIC01 Rx", NULL, "DMIC AIF" }, | 115 | { "DMIC01 Rx", NULL, "DMIC AIF" }, |
| @@ -117,6 +122,49 @@ static const struct snd_soc_dapm_route kabylake_map[] = { · 6 unmodified lines | |||
| 117 | { "iDisp1 Tx", NULL, "iDisp1_out"}, | 122 | { "iDisp1 Tx", NULL, "iDisp1_out"}, |
| 118 | }; | 123 | }; |
| 119 | 124 | ||
| 125 | enum { | ||
| 126 | KBL_DPCM_AUDIO_5663_PB = 0, | ||
| 127 | KBL_DPCM_AUDIO_5663_CP, | ||
| 128 | KBL_DPCM_AUDIO_5663_HDMI1_PB, | ||
| 129 | KBL_DPCM_AUDIO_5663_HDMI2_PB, | ||
| 130 | }; | ||
| 131 | |||
| 132 | static const struct snd_kcontrol_new kabylake_5663_controls[] = { | ||
| 133 | SOC_DAPM_PIN_SWITCH("Headphone Jack"), | ||
| 134 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
| 135 | }; | ||
| 136 | |||
| 137 | static const struct snd_soc_dapm_widget kabylake_5663_widgets[] = { | ||
| 138 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
| 139 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
| 140 | SND_SOC_DAPM_SPK("DP", NULL), | ||
| 141 | SND_SOC_DAPM_SPK("HDMI", NULL), | ||
| 142 | }; | ||
| 143 | |||
| 144 | static const struct snd_soc_dapm_route kabylake_5663_map[] = { | ||
| 145 | { "Headphone Jack", NULL, "HPOL" }, | ||
| 146 | { "Headphone Jack", NULL, "HPOR" }, | ||
| 147 | |||
| 148 | /* other jacks */ | ||
| 149 | { "IN1P", NULL, "Headset Mic" }, | ||
| 150 | { "IN1N", NULL, "Headset Mic" }, | ||
| 151 | |||
| 152 | { "HDMI", NULL, "hif5 Output" }, | ||
| 153 | { "DP", NULL, "hif6 Output" }, | ||
| 154 | |||
| 155 | /* CODEC BE connections */ | ||
| 156 | { "AIF Playback", NULL, "ssp1 Tx" }, | ||
| 157 | { "ssp1 Tx", NULL, "codec1_out" }, | ||
| 158 | |||
| 159 | { "codec0_in", NULL, "ssp1 Rx" }, | ||
| 160 | { "ssp1 Rx", NULL, "AIF Capture" }, | ||
| 161 | |||
| 162 | { "hifi2", NULL, "iDisp2 Tx"}, | ||
| 163 | { "iDisp2 Tx", NULL, "iDisp2_out"}, | ||
| 164 | { "hifi1", NULL, "iDisp1 Tx"}, | ||
| 165 | { "iDisp1 Tx", NULL, "iDisp1_out"}, | ||
| 166 | }; | ||
| 167 | |||
| 120 | static struct snd_soc_codec_conf max98927_codec_conf[] = { | 168 | static struct snd_soc_codec_conf max98927_codec_conf[] = { |
| 121 | { | 169 | { |
| 122 | .dev_name = MAXIM_DEV0_NAME, | 170 | .dev_name = MAXIM_DEV0_NAME, |
| @@ -165,7 +213,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) · 42 unmodified lines | |||
| 165 | * Headset buttons map to the google Reference headset. | 213 | * Headset buttons map to the google Reference headset. |
| 166 | * These can be configured by userspace. | 214 | * These can be configured by userspace. |
| 167 | */ | 215 | */ |
| 168 | ret = snd_soc_card_jack_new(&kabylake_audio_card, "Headset Jack", | 216 | ret = snd_soc_card_jack_new(kabylake_audio_card, "Headset Jack", |
| 169 | SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | 217 | SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
| 170 | SND_JACK_BTN_2 | SND_JACK_BTN_3, &ctx->kabylake_headset, | 218 | SND_JACK_BTN_2 | SND_JACK_BTN_3, &ctx->kabylake_headset, |
| 171 | NULL, 0); | 219 | NULL, 0); |
| @@ -173,8 +221,18 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) · 1 unmodified line | |||
| 173 | dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); | 221 | dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); |
| 174 | return ret; | 222 | return ret; |
| 175 | } | 223 | } |
| 176 | |||
| 177 | rt5663_set_jack_detect(codec, &ctx->kabylake_headset); | 224 | rt5663_set_jack_detect(codec, &ctx->kabylake_headset); |
| 225 | return ret; | ||
| 226 | } | ||
| 227 | |||
| 228 | static int kabylake_rt5663_max98927_codec_init(struct snd_soc_pcm_runtime *rtd) | ||
| 229 | { | ||
| 230 | int ret; | ||
| 231 | |||
| 232 | ret = kabylake_rt5663_codec_init(rtd); | ||
| 233 | if (ret) | ||
| 234 | return ret; | ||
| 235 | |||
| 178 | ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); | 236 | ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); |
| 179 | if (ret) { | 237 | if (ret) { |
| 180 | dev_err(rtd->dev, "SoC DMIC ignore suspend failed %d\n", ret); | 238 | dev_err(rtd->dev, "SoC DMIC ignore suspend failed %d\n", ret); |
| @@ -184,7 +242,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) · 3 unmodified lines | |||
| 184 | return ret; | 242 | return ret; |
| 185 | } | 243 | } |
| 186 | 244 | ||
| 187 | static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) | 245 | static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) |
| 188 | { | 246 | { |
| 189 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); | 247 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); |
| 190 | struct snd_soc_dai *dai = rtd->codec_dai; | 248 | struct snd_soc_dai *dai = rtd->codec_dai; |
| @@ -194,7 +252,7 @@ static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) · 3 unmodified lines | |||
| 194 | if (!pcm) | 252 | if (!pcm) |
| 195 | return -ENOMEM; | 253 | return -ENOMEM; |
| 196 | 254 | ||
| 197 | pcm->device = KBL_DPCM_AUDIO_HDMI1_PB; | 255 | pcm->device = device; |
| 198 | pcm->codec_dai = dai; | 256 | pcm->codec_dai = dai; |
| 199 | 257 | ||
| 200 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | 258 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); |
| @@ -202,47 +260,36 @@ static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) · 1 unmodified line | |||
| 202 | return 0; | 260 | return 0; |
| 203 | } | 261 | } |
| 204 | 262 | ||
| 205 | static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) | 263 | static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) |
| 206 | { | 264 | { |
| 207 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); | 265 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB); |
| 208 | struct snd_soc_dai *dai = rtd->codec_dai; | 266 | } |
| 209 | struct kbl_hdmi_pcm *pcm; | ||
| 210 | |||
| 211 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
| 212 | if (!pcm) | ||
| 213 | return -ENOMEM; | ||
| 214 | |||
| 215 | pcm->device = KBL_DPCM_AUDIO_HDMI2_PB; | ||
| 216 | pcm->codec_dai = dai; | ||
| 217 | |||
| 218 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
| 219 | 267 | ||
| 220 | return 0; | 268 | static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) |
| 269 | { | ||
| 270 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB); | ||
| 221 | } | 271 | } |
| 222 | 272 | ||
| 223 | static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) | 273 | static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) |
| 224 | { | 274 | { |
| 225 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); | 275 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI3_PB); |
| 226 | struct snd_soc_dai *dai = rtd->codec_dai; | 276 | } |
| 227 | struct kbl_hdmi_pcm *pcm; | ||
| 228 | |||
| 229 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
| 230 | if (!pcm) | ||
| 231 | return -ENOMEM; | ||
| 232 | |||
| 233 | pcm->device = KBL_DPCM_AUDIO_HDMI3_PB; | ||
| 234 | pcm->codec_dai = dai; | ||
| 235 | 277 | ||
| 236 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | 278 | static int kabylake_5663_hdmi1_init(struct snd_soc_pcm_runtime *rtd) |
| 279 | { | ||
| 280 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_5663_HDMI1_PB); | ||
| 281 | } | ||
| 237 | 282 | ||
| 238 | return 0; | 283 | static int kabylake_5663_hdmi2_init(struct snd_soc_pcm_runtime *rtd) |
| 284 | { | ||
| 285 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_5663_HDMI2_PB); | ||
| 239 | } | 286 | } |
| 240 | 287 | ||
| 241 | static unsigned int rates[] = { | 288 | static unsigned int rates[] = { |
| 242 | 48000, | 289 | 48000, |
| 243 | }; | 290 | }; |
| 244 | 291 | ||
| 245 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 292 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
| 246 | .count = ARRAY_SIZE(rates), | 293 | .count = ARRAY_SIZE(rates), |
| 247 | .list = rates, | 294 | .list = rates, |
| 248 | .mask = 0, | 295 | .mask = 0, |
| @@ -252,7 +299,7 @@ static unsigned int channels[] = { · 3 unmodified lines | |||
| 252 | 2, | 299 | 2, |
| 253 | }; | 300 | }; |
| 254 | 301 | ||
| 255 | static struct snd_pcm_hw_constraint_list constraints_channels = { | 302 | static const struct snd_pcm_hw_constraint_list constraints_channels = { |
| 256 | .count = ARRAY_SIZE(channels), | 303 | .count = ARRAY_SIZE(channels), |
| 257 | .list = channels, | 304 | .list = channels, |
| 258 | .mask = 0, | 305 | .mask = 0, |
| @@ -312,11 +359,13 @@ static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, · 53 unmodified lines | |||
| 312 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 359 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
| 313 | int ret; | 360 | int ret; |
| 314 | 361 | ||
| 315 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
| 316 | RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); | ||
| 317 | /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ | 362 | /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ |
| 318 | rt5663_sel_asrc_clk_src(codec_dai->codec, RT5663_DA_STEREO_FILTER, 1); | 363 | rt5663_sel_asrc_clk_src(codec_dai->codec, |
| 364 | RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER, | ||
| 365 | RT5663_CLK_SEL_I2S1_ASRC); | ||
| 319 | 366 | ||
| 367 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
| 368 | RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); | ||
| 320 | if (ret < 0) | 369 | if (ret < 0) |
| 321 | dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); | 370 | dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); |
| 322 | 371 | ||
| @@ -381,7 +430,7 @@ static unsigned int rates_16000[] = { · 58 unmodified lines | |||
| 381 | 16000, | 430 | 16000, |
| 382 | }; | 431 | }; |
| 383 | 432 | ||
| 384 | static struct snd_pcm_hw_constraint_list constraints_16000 = { | 433 | static const struct snd_pcm_hw_constraint_list constraints_16000 = { |
| 385 | .count = ARRAY_SIZE(rates_16000), | 434 | .count = ARRAY_SIZE(rates_16000), |
| 386 | .list = rates_16000, | 435 | .list = rates_16000, |
| 387 | }; | 436 | }; |
| @@ -443,6 +492,28 @@ static struct snd_soc_dai_link kabylake_dais[] = { · 55 unmodified lines | |||
| 443 | .dpcm_capture = 1, | 492 | .dpcm_capture = 1, |
| 444 | .ops = &kabylake_rt5663_fe_ops, | 493 | .ops = &kabylake_rt5663_fe_ops, |
| 445 | }, | 494 | }, |
| 495 | [KBL_DPCM_AUDIO_HS_PB] = { | ||
| 496 | .name = "Kbl Audio Headset Playback", | ||
| 497 | .stream_name = "Headset Audio", | ||
| 498 | .cpu_dai_name = "System Pin2", | ||
| 499 | .codec_name = "snd-soc-dummy", | ||
| 500 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 501 | .platform_name = "0000:00:1f.3", | ||
| 502 | .dpcm_playback = 1, | ||
| 503 | .nonatomic = 1, | ||
| 504 | .dynamic = 1, | ||
| 505 | }, | ||
| 506 | [KBL_DPCM_AUDIO_ECHO_REF_CP] = { | ||
| 507 | .name = "Kbl Audio Echo Reference cap", | ||
| 508 | .stream_name = "Echoreference Capture", | ||
| 509 | .cpu_dai_name = "Echoref Pin", | ||
| 510 | .codec_name = "snd-soc-dummy", | ||
| 511 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 512 | .platform_name = "0000:00:1f.3", | ||
| 513 | .init = NULL, | ||
| 514 | .capture_only = 1, | ||
| 515 | .nonatomic = 1, | ||
| 516 | }, | ||
| 446 | [KBL_DPCM_AUDIO_REF_CP] = { | 517 | [KBL_DPCM_AUDIO_REF_CP] = { |
| 447 | .name = "Kbl Audio Reference cap", | 518 | .name = "Kbl Audio Reference cap", |
| 448 | .stream_name = "Wake on Voice", | 519 | .stream_name = "Wake on Voice", |
| @@ -538,7 +609,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { · 89 unmodified lines | |||
| 538 | .no_pcm = 1, | 609 | .no_pcm = 1, |
| 539 | .codec_name = "i2c-10EC5663:00", | 610 | .codec_name = "i2c-10EC5663:00", |
| 540 | .codec_dai_name = KBL_REALTEK_CODEC_DAI, | 611 | .codec_dai_name = KBL_REALTEK_CODEC_DAI, |
| 541 | .init = kabylake_rt5663_codec_init, | 612 | .init = kabylake_rt5663_max98927_codec_init, |
| 542 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 613 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
| 543 | SND_SOC_DAIFMT_CBS_CFS, | 614 | SND_SOC_DAIFMT_CBS_CFS, |
| 544 | .ignore_pmdown_time = 1, | 615 | .ignore_pmdown_time = 1, |
| @@ -594,15 +665,119 @@ static struct snd_soc_dai_link kabylake_dais[] = { · 49 unmodified lines | |||
| 594 | }, | 665 | }, |
| 595 | }; | 666 | }; |
| 596 | 667 | ||
| 668 | static struct snd_soc_dai_link kabylake_5663_dais[] = { | ||
| 669 | /* Front End DAI links */ | ||
| 670 | [KBL_DPCM_AUDIO_5663_PB] = { | ||
| 671 | .name = "Kbl Audio Port", | ||
| 672 | .stream_name = "Audio", | ||
| 673 | .cpu_dai_name = "System Pin", | ||
| 674 | .platform_name = "0000:00:1f.3", | ||
| 675 | .dynamic = 1, | ||
| 676 | .codec_name = "snd-soc-dummy", | ||
| 677 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 678 | .nonatomic = 1, | ||
| 679 | .trigger = { | ||
| 680 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 681 | .dpcm_playback = 1, | ||
| 682 | .ops = &kabylake_rt5663_fe_ops, | ||
| 683 | }, | ||
| 684 | [KBL_DPCM_AUDIO_5663_CP] = { | ||
| 685 | .name = "Kbl Audio Capture Port", | ||
| 686 | .stream_name = "Audio Record", | ||
| 687 | .cpu_dai_name = "System Pin", | ||
| 688 | .platform_name = "0000:00:1f.3", | ||
| 689 | .dynamic = 1, | ||
| 690 | .codec_name = "snd-soc-dummy", | ||
| 691 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 692 | .nonatomic = 1, | ||
| 693 | .trigger = { | ||
| 694 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 695 | .dpcm_capture = 1, | ||
| 696 | .ops = &kabylake_rt5663_fe_ops, | ||
| 697 | }, | ||
| 698 | [KBL_DPCM_AUDIO_5663_HDMI1_PB] = { | ||
| 699 | .name = "Kbl HDMI Port1", | ||
| 700 | .stream_name = "Hdmi1", | ||
| 701 | .cpu_dai_name = "HDMI1 Pin", | ||
| 702 | .codec_name = "snd-soc-dummy", | ||
| 703 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 704 | .platform_name = "0000:00:1f.3", | ||
| 705 | .dpcm_playback = 1, | ||
| 706 | .init = NULL, | ||
| 707 | .trigger = { | ||
| 708 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 709 | .nonatomic = 1, | ||
| 710 | .dynamic = 1, | ||
| 711 | }, | ||
| 712 | [KBL_DPCM_AUDIO_5663_HDMI2_PB] = { | ||
| 713 | .name = "Kbl HDMI Port2", | ||
| 714 | .stream_name = "Hdmi2", | ||
| 715 | .cpu_dai_name = "HDMI2 Pin", | ||
| 716 | .codec_name = "snd-soc-dummy", | ||
| 717 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 718 | .platform_name = "0000:00:1f.3", | ||
| 719 | .dpcm_playback = 1, | ||
| 720 | .init = NULL, | ||
| 721 | .trigger = { | ||
| 722 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 723 | .nonatomic = 1, | ||
| 724 | .dynamic = 1, | ||
| 725 | }, | ||
| 726 | |||
| 727 | /* Back End DAI links */ | ||
| 728 | { | ||
| 729 | /* SSP1 - Codec */ | ||
| 730 | .name = "SSP1-Codec", | ||
| 731 | .id = 0, | ||
| 732 | .cpu_dai_name = "SSP1 Pin", | ||
| 733 | .platform_name = "0000:00:1f.3", | ||
| 734 | .no_pcm = 1, | ||
| 735 | .codec_name = "i2c-10EC5663:00", | ||
| 736 | .codec_dai_name = KBL_REALTEK_CODEC_DAI, | ||
| 737 | .init = kabylake_rt5663_codec_init, | ||
| 738 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
| 739 | SND_SOC_DAIFMT_CBS_CFS, | ||
| 740 | .ignore_pmdown_time = 1, | ||
| 741 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
| 742 | .ops = &kabylake_rt5663_ops, | ||
| 743 | .dpcm_playback = 1, | ||
| 744 | .dpcm_capture = 1, | ||
| 745 | }, | ||
| 746 | { | ||
| 747 | .name = "iDisp1", | ||
| 748 | .id = 1, | ||
| 749 | .cpu_dai_name = "iDisp1 Pin", | ||
| 750 | .codec_name = "ehdaudio0D2", | ||
| 751 | .codec_dai_name = "intel-hdmi-hifi1", | ||
| 752 | .platform_name = "0000:00:1f.3", | ||
| 753 | .dpcm_playback = 1, | ||
| 754 | .init = kabylake_5663_hdmi1_init, | ||
| 755 | .no_pcm = 1, | ||
| 756 | }, | ||
| 757 | { | ||
| 758 | .name = "iDisp2", | ||
| 759 | .id = 2, | ||
| 760 | .cpu_dai_name = "iDisp2 Pin", | ||
| 761 | .codec_name = "ehdaudio0D2", | ||
| 762 | .codec_dai_name = "intel-hdmi-hifi2", | ||
| 763 | .platform_name = "0000:00:1f.3", | ||
| 764 | .init = kabylake_5663_hdmi2_init, | ||
| 765 | .dpcm_playback = 1, | ||
| 766 | .no_pcm = 1, | ||
| 767 | }, | ||
| 768 | }; | ||
| 769 | |||
| 597 | #define NAME_SIZE 32 | 770 | #define NAME_SIZE 32 |
| 598 | static int kabylake_card_late_probe(struct snd_soc_card *card) | 771 | static int kabylake_card_late_probe(struct snd_soc_card *card) |
| 599 | { | 772 | { |
| 600 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(card); | 773 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(card); |
| 601 | struct kbl_hdmi_pcm *pcm; | 774 | struct kbl_hdmi_pcm *pcm; |
| 775 | struct snd_soc_codec *codec = NULL; | ||
| 602 | int err, i = 0; | 776 | int err, i = 0; |
| 603 | char jack_name[NAME_SIZE]; | 777 | char jack_name[NAME_SIZE]; |
| 604 | 778 | ||
| 605 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | 779 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { |
| 780 | codec = pcm->codec_dai->codec; | ||
| 606 | snprintf(jack_name, sizeof(jack_name), | 781 | snprintf(jack_name, sizeof(jack_name), |
| 607 | "HDMI/DP, pcm=%d Jack", pcm->device); | 782 | "HDMI/DP, pcm=%d Jack", pcm->device); |
| 608 | err = snd_soc_card_jack_new(card, jack_name, | 783 | err = snd_soc_card_jack_new(card, jack_name, |
| @@ -620,11 +795,14 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) · 11 unmodified lines | |||
| 620 | i++; | 795 | i++; |
| 621 | } | 796 | } |
| 622 | 797 | ||
| 623 | return 0; | 798 | if (!codec) |
| 799 | return -EINVAL; | ||
| 800 | |||
| 801 | return hdac_hdmi_jack_port_init(codec, &card->dapm); | ||
| 624 | } | 802 | } |
| 625 | 803 | ||
| 626 | /* kabylake audio machine driver for SPT + RT5663 */ | 804 | /* kabylake audio machine driver for SPT + RT5663 */ |
| 627 | static struct snd_soc_card kabylake_audio_card = { | 805 | static struct snd_soc_card kabylake_audio_card_rt5663_m98927 = { |
| 628 | .name = "kblrt5663max", | 806 | .name = "kblrt5663max", |
| 629 | .owner = THIS_MODULE, | 807 | .owner = THIS_MODULE, |
| 630 | .dai_link = kabylake_dais, | 808 | .dai_link = kabylake_dais, |
| @@ -641,6 +819,22 @@ static struct snd_soc_card kabylake_audio_card = { · 10 unmodified lines | |||
| 641 | .late_probe = kabylake_card_late_probe, | 819 | .late_probe = kabylake_card_late_probe, |
| 642 | }; | 820 | }; |
| 643 | 821 | ||
| 822 | /* kabylake audio machine driver for RT5663 */ | ||
| 823 | static struct snd_soc_card kabylake_audio_card_rt5663 = { | ||
| 824 | .name = "kblrt5663", | ||
| 825 | .owner = THIS_MODULE, | ||
| 826 | .dai_link = kabylake_5663_dais, | ||
| 827 | .num_links = ARRAY_SIZE(kabylake_5663_dais), | ||
| 828 | .controls = kabylake_5663_controls, | ||
| 829 | .num_controls = ARRAY_SIZE(kabylake_5663_controls), | ||
| 830 | .dapm_widgets = kabylake_5663_widgets, | ||
| 831 | .num_dapm_widgets = ARRAY_SIZE(kabylake_5663_widgets), | ||
| 832 | .dapm_routes = kabylake_5663_map, | ||
| 833 | .num_dapm_routes = ARRAY_SIZE(kabylake_5663_map), | ||
| 834 | .fully_routed = true, | ||
| 835 | .late_probe = kabylake_card_late_probe, | ||
| 836 | }; | ||
| 837 | |||
| 644 | static int kabylake_audio_probe(struct platform_device *pdev) | 838 | static int kabylake_audio_probe(struct platform_device *pdev) |
| 645 | { | 839 | { |
| 646 | struct kbl_rt5663_private *ctx; | 840 | struct kbl_rt5663_private *ctx; |
| @@ -652,19 +846,30 @@ static int kabylake_audio_probe(struct platform_device *pdev) · 5 unmodified lines | |||
| 652 | 846 | ||
| 653 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); | 847 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); |
| 654 | 848 | ||
| 655 | kabylake_audio_card.dev = &pdev->dev; | 849 | kabylake_audio_card = |
| 656 | snd_soc_card_set_drvdata(&kabylake_audio_card, ctx); | 850 | (struct snd_soc_card *)pdev->id_entry->driver_data; |
| 851 | |||
| 852 | kabylake_audio_card->dev = &pdev->dev; | ||
| 853 | snd_soc_card_set_drvdata(kabylake_audio_card, ctx); | ||
| 657 | 854 | ||
| 658 | pdata = dev_get_drvdata(&pdev->dev); | 855 | pdata = dev_get_drvdata(&pdev->dev); |
| 659 | if (pdata) | 856 | if (pdata) |
| 660 | dmic_constraints = pdata->dmic_num == 2 ? | 857 | dmic_constraints = pdata->dmic_num == 2 ? |
| 661 | &constraints_dmic_2ch : &constraints_dmic_channels; | 858 | &constraints_dmic_2ch : &constraints_dmic_channels; |
| 662 | 859 | ||
| 663 | return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card); | 860 | return devm_snd_soc_register_card(&pdev->dev, kabylake_audio_card); |
| 664 | } | 861 | } |
| 665 | 862 | ||
| 666 | static const struct platform_device_id kbl_board_ids[] = { | 863 | static const struct platform_device_id kbl_board_ids[] = { |
| 667 | { .name = "kbl_rt5663_m98927" }, | 864 | { |
| 865 | .name = "kbl_rt5663", | ||
| 866 | .driver_data = (kernel_ulong_t)&kabylake_audio_card_rt5663, | ||
| 867 | }, | ||
| 868 | { | ||
| 869 | .name = "kbl_rt5663_m98927", | ||
| 870 | .driver_data = | ||
| 871 | (kernel_ulong_t)&kabylake_audio_card_rt5663_m98927, | ||
| 872 | }, | ||
| 668 | { } | 873 | { } |
| 669 | }; | 874 | }; |
| 670 | 875 | ||
| @@ -684,4 +889,5 @@ MODULE_DESCRIPTION("Audio Machine driver-RT5663 & MAX98927 in I2S mode"); · 13 unmodified lines | |||
| 684 | MODULE_AUTHOR("Naveen M <naveen.m@intel.com>"); | 889 | MODULE_AUTHOR("Naveen M <naveen.m@intel.com>"); |
| 685 | MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); | 890 | MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); |
| 686 | MODULE_LICENSE("GPL v2"); | 891 | MODULE_LICENSE("GPL v2"); |
| 892 | MODULE_ALIAS("platform:kbl_rt5663"); | ||
| 687 | MODULE_ALIAS("platform:kbl_rt5663_m98927"); | 893 | MODULE_ALIAS("platform:kbl_rt5663_m98927"); |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/input.h> | ||
| 21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 22 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
| @@ -62,7 +63,10 @@ struct kbl_codec_private { · 38 unmodified lines | |||
| 62 | enum { | 63 | enum { |
| 63 | KBL_DPCM_AUDIO_PB = 0, | 64 | KBL_DPCM_AUDIO_PB = 0, |
| 64 | KBL_DPCM_AUDIO_CP, | 65 | KBL_DPCM_AUDIO_CP, |
| 66 | KBL_DPCM_AUDIO_HS_PB, | ||
| 67 | KBL_DPCM_AUDIO_ECHO_REF_CP, | ||
| 65 | KBL_DPCM_AUDIO_DMIC_CP, | 68 | KBL_DPCM_AUDIO_DMIC_CP, |
| 69 | KBL_DPCM_AUDIO_RT5514_DSP, | ||
| 66 | KBL_DPCM_AUDIO_HDMI1_PB, | 70 | KBL_DPCM_AUDIO_HDMI1_PB, |
| 67 | KBL_DPCM_AUDIO_HDMI2_PB, | 71 | KBL_DPCM_AUDIO_HDMI2_PB, |
| 68 | }; | 72 | }; |
| @@ -81,8 +85,8 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = { · 12 unmodified lines | |||
| 81 | SND_SOC_DAPM_SPK("Left Spk", NULL), | 85 | SND_SOC_DAPM_SPK("Left Spk", NULL), |
| 82 | SND_SOC_DAPM_SPK("Right Spk", NULL), | 86 | SND_SOC_DAPM_SPK("Right Spk", NULL), |
| 83 | SND_SOC_DAPM_MIC("DMIC", NULL), | 87 | SND_SOC_DAPM_MIC("DMIC", NULL), |
| 84 | SND_SOC_DAPM_SPK("DP", NULL), | 88 | SND_SOC_DAPM_SPK("HDMI1", NULL), |
| 85 | SND_SOC_DAPM_SPK("HDMI", NULL), | 89 | SND_SOC_DAPM_SPK("HDMI2", NULL), |
| 86 | 90 | ||
| 87 | }; | 91 | }; |
| 88 | 92 | ||
| @@ -99,23 +103,25 @@ static const struct snd_soc_dapm_route kabylake_map[] = { · 10 unmodified lines | |||
| 99 | { "IN1P", NULL, "Headset Mic" }, | 103 | { "IN1P", NULL, "Headset Mic" }, |
| 100 | { "IN1N", NULL, "Headset Mic" }, | 104 | { "IN1N", NULL, "Headset Mic" }, |
| 101 | 105 | ||
| 102 | { "HDMI", NULL, "hif5 Output" }, | ||
| 103 | { "DP", NULL, "hif6 Output" }, | ||
| 104 | |||
| 105 | /* CODEC BE connections */ | 106 | /* CODEC BE connections */ |
| 106 | { "Left HiFi Playback", NULL, "ssp0 Tx" }, | 107 | { "Left HiFi Playback", NULL, "ssp0 Tx" }, |
| 107 | { "Right HiFi Playback", NULL, "ssp0 Tx" }, | 108 | { "Right HiFi Playback", NULL, "ssp0 Tx" }, |
| 108 | { "ssp0 Tx", NULL, "codec0_out" }, | 109 | { "ssp0 Tx", NULL, "spk_out" }, |
| 109 | 110 | ||
| 110 | { "AIF Playback", NULL, "ssp1 Tx" }, | 111 | { "AIF Playback", NULL, "ssp1 Tx" }, |
| 111 | { "ssp1 Tx", NULL, "codec1_out" }, | 112 | { "ssp1 Tx", NULL, "hs_out" }, |
| 112 | 113 | ||
| 113 | { "codec0_in", NULL, "ssp1 Rx" }, | 114 | { "hs_in", NULL, "ssp1 Rx" }, |
| 114 | { "ssp1 Rx", NULL, "AIF Capture" }, | 115 | { "ssp1 Rx", NULL, "AIF Capture" }, |
| 115 | 116 | ||
| 116 | { "codec1_in", NULL, "ssp0 Rx" }, | 117 | { "codec1_in", NULL, "ssp0 Rx" }, |
| 117 | { "ssp0 Rx", NULL, "AIF1 Capture" }, | 118 | { "ssp0 Rx", NULL, "AIF1 Capture" }, |
| 118 | 119 | ||
| 120 | /* IV feedback path */ | ||
| 121 | { "codec0_fb_in", NULL, "ssp0 Rx"}, | ||
| 122 | { "ssp0 Rx", NULL, "Left HiFi Capture" }, | ||
| 123 | { "ssp0 Rx", NULL, "Right HiFi Capture" }, | ||
| 124 | |||
| 119 | /* DMIC */ | 125 | /* DMIC */ |
| 120 | { "DMIC1L", NULL, "DMIC" }, | 126 | { "DMIC1L", NULL, "DMIC" }, |
| 121 | { "DMIC1R", NULL, "DMIC" }, | 127 | { "DMIC1R", NULL, "DMIC" }, |
| @@ -173,6 +179,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) · 51 unmodified lines | |||
| 173 | int ret; | 179 | int ret; |
| 174 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); | 180 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); |
| 175 | struct snd_soc_codec *codec = rtd->codec; | 181 | struct snd_soc_codec *codec = rtd->codec; |
| 182 | struct snd_soc_jack *jack; | ||
| 176 | 183 | ||
| 177 | /* | 184 | /* |
| 178 | * Headset buttons map to the google Reference headset. | 185 | * Headset buttons map to the google Reference headset. |
| @@ -187,6 +194,12 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) · 8 unmodified lines | |||
| 187 | return ret; | 194 | return ret; |
| 188 | } | 195 | } |
| 189 | 196 | ||
| 197 | jack = &ctx->kabylake_headset; | ||
| 198 | snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA); | ||
| 199 | snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); | ||
| 200 | snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); | ||
| 201 | snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); | ||
| 202 | |||
| 190 | rt5663_set_jack_detect(codec, &ctx->kabylake_headset); | 203 | rt5663_set_jack_detect(codec, &ctx->kabylake_headset); |
| 191 | 204 | ||
| 192 | ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "DMIC"); | 205 | ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "DMIC"); |
| @@ -358,11 +371,18 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, · 165 unmodified lines | |||
| 358 | return ret; | 371 | return ret; |
| 359 | } | 372 | } |
| 360 | } | 373 | } |
| 361 | if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME) || | 374 | if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) { |
| 362 | !strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) { | 375 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); |
| 363 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF0, 3, 8, 16); | ||
| 364 | if (ret < 0) { | 376 | if (ret < 0) { |
| 365 | dev_err(rtd->dev, "set TDM slot err:%d\n", ret); | 377 | dev_err(rtd->dev, "DEV0 TDM slot err:%d\n", ret); |
| 378 | return ret; | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 382 | if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) { | ||
| 383 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16); | ||
| 384 | if (ret < 0) { | ||
| 385 | dev_err(rtd->dev, "DEV1 TDM slot err:%d\n", ret); | ||
| 366 | return ret; | 386 | return ret; |
| 367 | } | 387 | } |
| 368 | } | 388 | } |
| @@ -442,6 +462,36 @@ static struct snd_soc_dai_link kabylake_dais[] = { · 73 unmodified lines | |||
| 442 | .dpcm_capture = 1, | 462 | .dpcm_capture = 1, |
| 443 | .ops = &kabylake_rt5663_fe_ops, | 463 | .ops = &kabylake_rt5663_fe_ops, |
| 444 | }, | 464 | }, |
| 465 | [KBL_DPCM_AUDIO_HS_PB] = { | ||
| 466 | .name = "Kbl Audio Headset Playback", | ||
| 467 | .stream_name = "Headset Audio", | ||
| 468 | .cpu_dai_name = "System Pin2", | ||
| 469 | .codec_name = "snd-soc-dummy", | ||
| 470 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 471 | .platform_name = "0000:00:1f.3", | ||
| 472 | .dpcm_playback = 1, | ||
| 473 | .nonatomic = 1, | ||
| 474 | .dynamic = 1, | ||
| 475 | }, | ||
| 476 | [KBL_DPCM_AUDIO_ECHO_REF_CP] = { | ||
| 477 | .name = "Kbl Audio Echo Reference cap", | ||
| 478 | .stream_name = "Echoreference Capture", | ||
| 479 | .cpu_dai_name = "Echoref Pin", | ||
| 480 | .codec_name = "snd-soc-dummy", | ||
| 481 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 482 | .platform_name = "0000:00:1f.3", | ||
| 483 | .init = NULL, | ||
| 484 | .capture_only = 1, | ||
| 485 | .nonatomic = 1, | ||
| 486 | }, | ||
| 487 | [KBL_DPCM_AUDIO_RT5514_DSP] = { | ||
| 488 | .name = "rt5514 dsp", | ||
| 489 | .stream_name = "Wake on Voice", | ||
| 490 | .cpu_dai_name = "spi-PRP0001:00", | ||
| 491 | .platform_name = "spi-PRP0001:00", | ||
| 492 | .codec_name = "snd-soc-dummy", | ||
| 493 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 494 | }, | ||
| 445 | [KBL_DPCM_AUDIO_DMIC_CP] = { | 495 | [KBL_DPCM_AUDIO_DMIC_CP] = { |
| 446 | .name = "Kbl Audio DMIC cap", | 496 | .name = "Kbl Audio DMIC cap", |
| 447 | .stream_name = "dmiccap", | 497 | .stream_name = "dmiccap", |
| @@ -548,10 +598,12 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) · 100 unmodified lines | |||
| 548 | { | 598 | { |
| 549 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); | 599 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); |
| 550 | struct kbl_hdmi_pcm *pcm; | 600 | struct kbl_hdmi_pcm *pcm; |
| 601 | struct snd_soc_codec *codec = NULL; | ||
| 551 | int err, i = 0; | 602 | int err, i = 0; |
| 552 | char jack_name[NAME_SIZE]; | 603 | char jack_name[NAME_SIZE]; |
| 553 | 604 | ||
| 554 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | 605 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { |
| 606 | codec = pcm->codec_dai->codec; | ||
| 555 | err = snd_soc_card_jack_new(card, jack_name, | 607 | err = snd_soc_card_jack_new(card, jack_name, |
| 556 | SND_JACK_AVOUT, &ctx->kabylake_hdmi[i], | 608 | SND_JACK_AVOUT, &ctx->kabylake_hdmi[i], |
| 557 | NULL, 0); | 609 | NULL, 0); |
| @@ -565,7 +617,10 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) · 7 unmodified lines | |||
| 565 | i++; | 617 | i++; |
| 566 | } | 618 | } |
| 567 | 619 | ||
| 568 | return 0; | 620 | if (!codec) |
| 621 | return -EINVAL; | ||
| 622 | |||
| 623 | return hdac_hdmi_jack_port_init(codec, &card->dapm); | ||
| 569 | } | 624 | } |
| 570 | 625 | ||
| 571 | /* | 626 | /* |
| @@ -376,10 +376,8 @@ static int snd_mfld_mc_probe(struct platform_device *pdev) · 375 unmodified lines | |||
| 376 | /* audio interrupt base of SRAM location where | 376 | /* audio interrupt base of SRAM location where |
| 377 | * interrupts are stored by System FW */ | 377 | * interrupts are stored by System FW */ |
| 378 | mc_drv_ctx = devm_kzalloc(&pdev->dev, sizeof(*mc_drv_ctx), GFP_ATOMIC); | 378 | mc_drv_ctx = devm_kzalloc(&pdev->dev, sizeof(*mc_drv_ctx), GFP_ATOMIC); |
| 379 | if (!mc_drv_ctx) { | 379 | if (!mc_drv_ctx) |
| 380 | pr_err("allocation failed\n"); | ||
| 381 | return -ENOMEM; | 380 | return -ENOMEM; |
| 382 | } | ||
| 383 | 381 | ||
| 384 | irq_mem = platform_get_resource_byname( | 382 | irq_mem = platform_get_resource_byname( |
| 385 | pdev, IORESOURCE_MEM, "IRQ_BASE"); | 383 | pdev, IORESOURCE_MEM, "IRQ_BASE"); |
| @@ -1135,7 +1135,7 @@ static int hsw_pcm_remove(struct snd_soc_platform *platform) · 1134 unmodified lines | |||
| 1135 | return 0; | 1135 | return 0; |
| 1136 | } | 1136 | } |
| 1137 | 1137 | ||
| 1138 | static struct snd_soc_platform_driver hsw_soc_platform = { | 1138 | static const struct snd_soc_platform_driver hsw_soc_platform = { |
| 1139 | .probe = hsw_pcm_probe, | 1139 | .probe = hsw_pcm_probe, |
| 1140 | .remove = hsw_pcm_remove, | 1140 | .remove = hsw_pcm_remove, |
| 1141 | .ops = &hsw_pcm_ops, | 1141 | .ops = &hsw_pcm_ops, |
| @@ -8,7 +8,8 @@ endif · 7 unmodified lines | |||
| 8 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o | 8 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o |
| 9 | 9 | ||
| 10 | # Skylake IPC Support | 10 | # Skylake IPC Support |
| 11 | snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o \ | 11 | snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o \ |
| 12 | skl-sst.o bxt-sst.o skl-sst-utils.o | 12 | skl-sst-cldma.o skl-sst.o bxt-sst.o cnl-sst.o \ |
| 13 | skl-sst-utils.o | ||
| 13 | 14 | ||
| 14 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o | 15 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o |
| @@ -530,7 +530,7 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) · 529 unmodified lines | |||
| 530 | return 0; | 530 | return 0; |
| 531 | } | 531 | } |
| 532 | 532 | ||
| 533 | static struct skl_dsp_fw_ops bxt_fw_ops = { | 533 | static const struct skl_dsp_fw_ops bxt_fw_ops = { |
| 534 | .set_state_D0 = bxt_set_dsp_D0, | 534 | .set_state_D0 = bxt_set_dsp_D0, |
| 535 | .set_state_D3 = bxt_set_dsp_D3, | 535 | .set_state_D3 = bxt_set_dsp_D3, |
| 536 | .set_state_D0i3 = bxt_schedule_dsp_D0i3, | 536 | .set_state_D0i3 = bxt_schedule_dsp_D0i3, |
| @@ -581,10 +581,15 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, · 44 unmodified lines | |||
| 581 | sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), | 581 | sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), |
| 582 | SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); | 582 | SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); |
| 583 | 583 | ||
| 584 | ret = skl_ipc_init(dev, skl); | ||
| 585 | if (ret) { | ||
| 586 | skl_dsp_free(sst); | ||
| 587 | return ret; | ||
| 588 | } | ||
| 589 | |||
| 584 | /* set the D0i3 check */ | 590 | /* set the D0i3 check */ |
| 585 | skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0; | 591 | skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0; |
| 586 | 592 | ||
| 587 | skl->cores.count = 2; | ||
| 588 | skl->boot_complete = false; | 593 | skl->boot_complete = false; |
| 589 | init_waitqueue_head(&skl->boot_wait); | 594 | init_waitqueue_head(&skl->boot_wait); |
| 590 | INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3); | 595 | INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3); |
| @@ -629,11 +634,6 @@ void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) · 38 unmodified lines | |||
| 629 | release_firmware(ctx->dsp->fw); | 634 | release_firmware(ctx->dsp->fw); |
| 630 | skl_freeup_uuid_list(ctx); | 635 | skl_freeup_uuid_list(ctx); |
| 631 | skl_ipc_free(&ctx->ipc); | 636 | skl_ipc_free(&ctx->ipc); |
| 632 | ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp); | ||
| 633 | |||
| 634 | if (ctx->dsp->addr.lpe) | ||
| 635 | iounmap(ctx->dsp->addr.lpe); | ||
| 636 | |||
| 637 | ctx->dsp->ops->free(ctx->dsp); | 637 | ctx->dsp->ops->free(ctx->dsp); |
| 638 | } | 638 | } |
| 639 | EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup); | 639 | EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup); |
| @@ -0,0 +1,274 @@ | |||
| 1 | /* | ||
| 2 | * cnl-sst-dsp.c - CNL SST library generic function | ||
| 3 | * | ||
| 4 | * Copyright (C) 2016-17, Intel Corporation. | ||
| 5 | * Author: Guneshwor Singh <guneshwor.o.singh@intel.com> | ||
| 6 | * | ||
| 7 | * Modified from: | ||
| 8 | * SKL SST library generic function | ||
| 9 | * Copyright (C) 2014-15, Intel Corporation. | ||
| 10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License as version 2, as | ||
| 14 | * published by the Free Software Foundation. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, but | ||
| 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 19 | * General Public License for more details. | ||
| 20 | * | ||
| 21 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 22 | */ | ||
| 23 | #include <linux/device.h> | ||
| 24 | #include "../common/sst-dsp.h" | ||
| 25 | #include "../common/sst-ipc.h" | ||
| 26 | #include "../common/sst-dsp-priv.h" | ||
| 27 | #include "cnl-sst-dsp.h" | ||
| 28 | |||
| 29 | /* various timeout values */ | ||
| 30 | #define CNL_DSP_PU_TO 50 | ||
| 31 | #define CNL_DSP_PD_TO 50 | ||
| 32 | #define CNL_DSP_RESET_TO 50 | ||
| 33 | |||
| 34 | static int | ||
| 35 | cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) | ||
| 36 | { | ||
| 37 | /* update bits */ | ||
| 38 | sst_dsp_shim_update_bits_unlocked(ctx, | ||
| 39 | CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask), | ||
| 40 | CNL_ADSPCS_CRST(core_mask)); | ||
| 41 | |||
| 42 | /* poll with timeout to check if operation successful */ | ||
| 43 | return sst_dsp_register_poll(ctx, | ||
| 44 | CNL_ADSP_REG_ADSPCS, | ||
| 45 | CNL_ADSPCS_CRST(core_mask), | ||
| 46 | CNL_ADSPCS_CRST(core_mask), | ||
| 47 | CNL_DSP_RESET_TO, | ||
| 48 | "Set reset"); | ||
| 49 | } | ||
| 50 | |||
| 51 | static int | ||
| 52 | cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask) | ||
| 53 | { | ||
| 54 | /* update bits */ | ||
| 55 | sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, | ||
| 56 | CNL_ADSPCS_CRST(core_mask), 0); | ||
| 57 | |||
| 58 | /* poll with timeout to check if operation successful */ | ||
| 59 | return sst_dsp_register_poll(ctx, | ||
| 60 | CNL_ADSP_REG_ADSPCS, | ||
| 61 | CNL_ADSPCS_CRST(core_mask), | ||
| 62 | 0, | ||
| 63 | CNL_DSP_RESET_TO, | ||
| 64 | "Unset reset"); | ||
| 65 | } | ||
| 66 | |||
| 67 | static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) | ||
| 68 | { | ||
| 69 | int val; | ||
| 70 | bool is_enable; | ||
| 71 | |||
| 72 | val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS); | ||
| 73 | |||
| 74 | is_enable = (val & CNL_ADSPCS_CPA(core_mask)) && | ||
| 75 | (val & CNL_ADSPCS_SPA(core_mask)) && | ||
| 76 | !(val & CNL_ADSPCS_CRST(core_mask)) && | ||
| 77 | !(val & CNL_ADSPCS_CSTALL(core_mask)); | ||
| 78 | |||
| 79 | dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n", | ||
| 80 | is_enable, core_mask); | ||
| 81 | |||
| 82 | return is_enable; | ||
| 83 | } | ||
| 84 | |||
| 85 | static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) | ||
| 86 | { | ||
| 87 | /* stall core */ | ||
| 88 | sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, | ||
| 89 | CNL_ADSPCS_CSTALL(core_mask), | ||
| 90 | CNL_ADSPCS_CSTALL(core_mask)); | ||
| 91 | |||
| 92 | /* set reset state */ | ||
| 93 | return cnl_dsp_core_set_reset_state(ctx, core_mask); | ||
| 94 | } | ||
| 95 | |||
| 96 | static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) | ||
| 97 | { | ||
| 98 | int ret; | ||
| 99 | |||
| 100 | /* unset reset state */ | ||
| 101 | ret = cnl_dsp_core_unset_reset_state(ctx, core_mask); | ||
| 102 | if (ret < 0) | ||
| 103 | return ret; | ||
| 104 | |||
| 105 | /* run core */ | ||
| 106 | sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, | ||
| 107 | CNL_ADSPCS_CSTALL(core_mask), 0); | ||
| 108 | |||
| 109 | if (!is_cnl_dsp_core_enable(ctx, core_mask)) { | ||
| 110 | cnl_dsp_reset_core(ctx, core_mask); | ||
| 111 | dev_err(ctx->dev, "DSP core mask %#x enable failed\n", | ||
| 112 | core_mask); | ||
| 113 | ret = -EIO; | ||
| 114 | } | ||
| 115 | |||
| 116 | return ret; | ||
| 117 | } | ||
| 118 | |||
| 119 | static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) | ||
| 120 | { | ||
| 121 | /* update bits */ | ||
| 122 | sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, | ||
| 123 | CNL_ADSPCS_SPA(core_mask), | ||
| 124 | CNL_ADSPCS_SPA(core_mask)); | ||
| 125 | |||
| 126 | /* poll with timeout to check if operation successful */ | ||
| 127 | return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS, | ||
| 128 | CNL_ADSPCS_CPA(core_mask), | ||
| 129 | CNL_ADSPCS_CPA(core_mask), | ||
| 130 | CNL_DSP_PU_TO, | ||
| 131 | "Power up"); | ||
| 132 | } | ||
| 133 | |||
| 134 | static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) | ||
| 135 | { | ||
| 136 | /* update bits */ | ||
| 137 | sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, | ||
| 138 | CNL_ADSPCS_SPA(core_mask), 0); | ||
| 139 | |||
| 140 | /* poll with timeout to check if operation successful */ | ||
| 141 | return sst_dsp_register_poll(ctx, | ||
| 142 | CNL_ADSP_REG_ADSPCS, | ||
| 143 | CNL_ADSPCS_CPA(core_mask), | ||
| 144 | 0, | ||
| 145 | CNL_DSP_PD_TO, | ||
| 146 | "Power down"); | ||
| 147 | } | ||
| 148 | |||
| 149 | int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) | ||
| 150 | { | ||
| 151 | int ret; | ||
| 152 | |||
| 153 | /* power up */ | ||
| 154 | ret = cnl_dsp_core_power_up(ctx, core_mask); | ||
| 155 | if (ret < 0) { | ||
| 156 | dev_dbg(ctx->dev, "DSP core mask %#x power up failed", | ||
| 157 | core_mask); | ||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | return cnl_dsp_start_core(ctx, core_mask); | ||
| 162 | } | ||
| 163 | |||
| 164 | int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) | ||
| 165 | { | ||
| 166 | int ret; | ||
| 167 | |||
| 168 | ret = cnl_dsp_reset_core(ctx, core_mask); | ||
| 169 | if (ret < 0) { | ||
| 170 | dev_err(ctx->dev, "DSP core mask %#x reset failed\n", | ||
| 171 | core_mask); | ||
| 172 | return ret; | ||
| 173 | } | ||
| 174 | |||
| 175 | /* power down core*/ | ||
| 176 | ret = cnl_dsp_core_power_down(ctx, core_mask); | ||
| 177 | if (ret < 0) { | ||
| 178 | dev_err(ctx->dev, "DSP core mask %#x power down failed\n", | ||
| 179 | core_mask); | ||
| 180 | return ret; | ||
| 181 | } | ||
| 182 | |||
| 183 | if (is_cnl_dsp_core_enable(ctx, core_mask)) { | ||
| 184 | dev_err(ctx->dev, "DSP core mask %#x disable failed\n", | ||
| 185 | core_mask); | ||
| 186 | ret = -EIO; | ||
| 187 | } | ||
| 188 | |||
| 189 | return ret; | ||
| 190 | } | ||
| 191 | |||
| 192 | irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id) | ||
| 193 | { | ||
| 194 | struct sst_dsp *ctx = dev_id; | ||
| 195 | u32 val; | ||
| 196 | irqreturn_t ret = IRQ_NONE; | ||
| 197 | |||
| 198 | spin_lock(&ctx->spinlock); | ||
| 199 | |||
| 200 | val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS); | ||
| 201 | ctx->intr_status = val; | ||
| 202 | |||
| 203 | if (val == 0xffffffff) { | ||
| 204 | spin_unlock(&ctx->spinlock); | ||
| 205 | return IRQ_NONE; | ||
| 206 | } | ||
| 207 | |||
| 208 | if (val & CNL_ADSPIS_IPC) { | ||
| 209 | cnl_ipc_int_disable(ctx); | ||
| 210 | ret = IRQ_WAKE_THREAD; | ||
| 211 | } | ||
| 212 | |||
| 213 | spin_unlock(&ctx->spinlock); | ||
| 214 | |||
| 215 | return ret; | ||
| 216 | } | ||
| 217 | |||
| 218 | void cnl_dsp_free(struct sst_dsp *dsp) | ||
| 219 | { | ||
| 220 | cnl_ipc_int_disable(dsp); | ||
| 221 | |||
| 222 | free_irq(dsp->irq, dsp); | ||
| 223 | cnl_ipc_op_int_disable(dsp); | ||
| 224 | cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); | ||
| 225 | } | ||
| 226 | EXPORT_SYMBOL_GPL(cnl_dsp_free); | ||
| 227 | |||
| 228 | void cnl_ipc_int_enable(struct sst_dsp *ctx) | ||
| 229 | { | ||
| 230 | sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC, | ||
| 231 | CNL_ADSPIC_IPC, CNL_ADSPIC_IPC); | ||
| 232 | } | ||
| 233 | |||
| 234 | void cnl_ipc_int_disable(struct sst_dsp *ctx) | ||
| 235 | { | ||
| 236 | sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC, | ||
| 237 | CNL_ADSPIC_IPC, 0); | ||
| 238 | } | ||
| 239 | |||
| 240 | void cnl_ipc_op_int_enable(struct sst_dsp *ctx) | ||
| 241 | { | ||
| 242 | /* enable IPC DONE interrupt */ | ||
| 243 | sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, | ||
| 244 | CNL_ADSP_REG_HIPCCTL_DONE, | ||
| 245 | CNL_ADSP_REG_HIPCCTL_DONE); | ||
| 246 | |||
| 247 | /* enable IPC BUSY interrupt */ | ||
| 248 | sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, | ||
| 249 | CNL_ADSP_REG_HIPCCTL_BUSY, | ||
| 250 | CNL_ADSP_REG_HIPCCTL_BUSY); | ||
| 251 | } | ||
| 252 | |||
| 253 | void cnl_ipc_op_int_disable(struct sst_dsp *ctx) | ||
| 254 | { | ||
| 255 | /* disable IPC DONE interrupt */ | ||
| 256 | sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, | ||
| 257 | CNL_ADSP_REG_HIPCCTL_DONE, 0); | ||
| 258 | |||
| 259 | /* disable IPC BUSY interrupt */ | ||
| 260 | sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, | ||
| 261 | CNL_ADSP_REG_HIPCCTL_BUSY, 0); | ||
| 262 | } | ||
| 263 | |||
| 264 | bool cnl_ipc_int_status(struct sst_dsp *ctx) | ||
| 265 | { | ||
| 266 | return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) & | ||
| 267 | CNL_ADSPIS_IPC; | ||
| 268 | } | ||
| 269 | |||
| 270 | void cnl_ipc_free(struct sst_generic_ipc *ipc) | ||
| 271 | { | ||
| 272 | cnl_ipc_op_int_disable(ipc->dsp); | ||
| 273 | sst_ipc_fini(ipc); | ||
| 274 | } | ||
| @@ -0,0 +1,112 @@ | |||
| 1 | /* | ||
| 2 | * Cannonlake SST DSP Support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2016-17, Intel Corporation. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as version 2, as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, but | ||
| 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | * General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef __CNL_SST_DSP_H__ | ||
| 17 | #define __CNL_SST_DSP_H__ | ||
| 18 | |||
| 19 | struct sst_dsp; | ||
| 20 | struct skl_sst; | ||
| 21 | struct sst_dsp_device; | ||
| 22 | struct sst_generic_ipc; | ||
| 23 | |||
| 24 | /* Intel HD Audio General DSP Registers */ | ||
| 25 | #define CNL_ADSP_GEN_BASE 0x0 | ||
| 26 | #define CNL_ADSP_REG_ADSPCS (CNL_ADSP_GEN_BASE + 0x04) | ||
| 27 | #define CNL_ADSP_REG_ADSPIC (CNL_ADSP_GEN_BASE + 0x08) | ||
| 28 | #define CNL_ADSP_REG_ADSPIS (CNL_ADSP_GEN_BASE + 0x0c) | ||
| 29 | |||
| 30 | /* Intel HD Audio Inter-Processor Communication Registers */ | ||
| 31 | #define CNL_ADSP_IPC_BASE 0xc0 | ||
| 32 | #define CNL_ADSP_REG_HIPCTDR (CNL_ADSP_IPC_BASE + 0x00) | ||
| 33 | #define CNL_ADSP_REG_HIPCTDA (CNL_ADSP_IPC_BASE + 0x04) | ||
| 34 | #define CNL_ADSP_REG_HIPCTDD (CNL_ADSP_IPC_BASE + 0x08) | ||
| 35 | #define CNL_ADSP_REG_HIPCIDR (CNL_ADSP_IPC_BASE + 0x10) | ||
| 36 | #define CNL_ADSP_REG_HIPCIDA (CNL_ADSP_IPC_BASE + 0x14) | ||
| 37 | #define CNL_ADSP_REG_HIPCIDD (CNL_ADSP_IPC_BASE + 0x18) | ||
| 38 | #define CNL_ADSP_REG_HIPCCTL (CNL_ADSP_IPC_BASE + 0x28) | ||
| 39 | |||
| 40 | /* HIPCTDR */ | ||
| 41 | #define CNL_ADSP_REG_HIPCTDR_BUSY BIT(31) | ||
| 42 | |||
| 43 | /* HIPCTDA */ | ||
| 44 | #define CNL_ADSP_REG_HIPCTDA_DONE BIT(31) | ||
| 45 | |||
| 46 | /* HIPCIDR */ | ||
| 47 | #define CNL_ADSP_REG_HIPCIDR_BUSY BIT(31) | ||
| 48 | |||
| 49 | /* HIPCIDA */ | ||
| 50 | #define CNL_ADSP_REG_HIPCIDA_DONE BIT(31) | ||
| 51 | |||
| 52 | /* CNL HIPCCTL */ | ||
| 53 | #define CNL_ADSP_REG_HIPCCTL_DONE BIT(1) | ||
| 54 | #define CNL_ADSP_REG_HIPCCTL_BUSY BIT(0) | ||
| 55 | |||
| 56 | /* CNL HIPCT */ | ||
| 57 | #define CNL_ADSP_REG_HIPCT_BUSY BIT(31) | ||
| 58 | |||
| 59 | /* Intel HD Audio SRAM Window 1 */ | ||
| 60 | #define CNL_ADSP_SRAM1_BASE 0xa0000 | ||
| 61 | |||
| 62 | #define CNL_ADSP_MMIO_LEN 0x10000 | ||
| 63 | |||
| 64 | #define CNL_ADSP_W0_STAT_SZ 0x1000 | ||
| 65 | |||
| 66 | #define CNL_ADSP_W0_UP_SZ 0x1000 | ||
| 67 | |||
| 68 | #define CNL_ADSP_W1_SZ 0x1000 | ||
| 69 | |||
| 70 | #define CNL_FW_STS_MASK 0xf | ||
| 71 | |||
| 72 | #define CNL_ADSPIC_IPC 0x1 | ||
| 73 | #define CNL_ADSPIS_IPC 0x1 | ||
| 74 | |||
| 75 | #define CNL_DSP_CORES 4 | ||
| 76 | #define CNL_DSP_CORES_MASK ((1 << CNL_DSP_CORES) - 1) | ||
| 77 | |||
| 78 | /* core reset - asserted high */ | ||
| 79 | #define CNL_ADSPCS_CRST_SHIFT 0 | ||
| 80 | #define CNL_ADSPCS_CRST(x) (x << CNL_ADSPCS_CRST_SHIFT) | ||
| 81 | |||
| 82 | /* core run/stall - when set to 1 core is stalled */ | ||
| 83 | #define CNL_ADSPCS_CSTALL_SHIFT 8 | ||
| 84 | #define CNL_ADSPCS_CSTALL(x) (x << CNL_ADSPCS_CSTALL_SHIFT) | ||
| 85 | |||
| 86 | /* set power active - when set to 1 turn core on */ | ||
| 87 | #define CNL_ADSPCS_SPA_SHIFT 16 | ||
| 88 | #define CNL_ADSPCS_SPA(x) (x << CNL_ADSPCS_SPA_SHIFT) | ||
| 89 | |||
| 90 | /* current power active - power status of cores, set by hardware */ | ||
| 91 | #define CNL_ADSPCS_CPA_SHIFT 24 | ||
| 92 | #define CNL_ADSPCS_CPA(x) (x << CNL_ADSPCS_CPA_SHIFT) | ||
| 93 | |||
| 94 | int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core); | ||
| 95 | int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core); | ||
| 96 | irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id); | ||
| 97 | void cnl_dsp_free(struct sst_dsp *dsp); | ||
| 98 | |||
| 99 | void cnl_ipc_int_enable(struct sst_dsp *ctx); | ||
| 100 | void cnl_ipc_int_disable(struct sst_dsp *ctx); | ||
| 101 | void cnl_ipc_op_int_enable(struct sst_dsp *ctx); | ||
| 102 | void cnl_ipc_op_int_disable(struct sst_dsp *ctx); | ||
| 103 | bool cnl_ipc_int_status(struct sst_dsp *ctx); | ||
| 104 | void cnl_ipc_free(struct sst_generic_ipc *ipc); | ||
| 105 | |||
| 106 | int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | ||
| 107 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, | ||
| 108 | struct skl_sst **dsp); | ||
| 109 | int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx); | ||
| 110 | void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); | ||
| 111 | |||
| 112 | #endif /*__CNL_SST_DSP_H__*/ | ||
| @@ -0,0 +1,497 @@ | |||
| 1 | /* | ||
| 2 | * cnl-sst.c - DSP library functions for CNL platform | ||
| 3 | * | ||
| 4 | * Copyright (C) 2016-17, Intel Corporation. | ||
| 5 | * | ||
| 6 | * Author: Guneshwor Singh <guneshwor.o.singh@intel.com> | ||
| 7 | * | ||
| 8 | * Modified from: | ||
| 9 | * HDA DSP library functions for SKL platform | ||
| 10 | * Copyright (C) 2014-15, Intel Corporation. | ||
| 11 | * | ||
| 12 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or modify | ||
| 15 | * it under the terms of the GNU General Public License as version 2, as | ||
| 16 | * published by the Free Software Foundation. | ||
| 17 | * | ||
| 18 | * This program is distributed in the hope that it will be useful, but | ||
| 19 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 21 | * General Public License for more details. | ||
| 22 | * | ||
| 23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/delay.h> | ||
| 28 | #include <linux/firmware.h> | ||
| 29 | #include <linux/device.h> | ||
| 30 | |||
| 31 | #include "../common/sst-dsp.h" | ||
| 32 | #include "../common/sst-dsp-priv.h" | ||
| 33 | #include "../common/sst-ipc.h" | ||
| 34 | #include "cnl-sst-dsp.h" | ||
| 35 | #include "skl-sst-dsp.h" | ||
| 36 | #include "skl-sst-ipc.h" | ||
| 37 | |||
| 38 | #define CNL_FW_ROM_INIT 0x1 | ||
| 39 | #define CNL_FW_INIT 0x5 | ||
| 40 | #define CNL_IPC_PURGE 0x01004000 | ||
| 41 | #define CNL_INIT_TIMEOUT 300 | ||
| 42 | #define CNL_BASEFW_TIMEOUT 3000 | ||
| 43 | |||
| 44 | #define CNL_ADSP_SRAM0_BASE 0x80000 | ||
| 45 | |||
| 46 | /* Firmware status window */ | ||
| 47 | #define CNL_ADSP_FW_STATUS CNL_ADSP_SRAM0_BASE | ||
| 48 | #define CNL_ADSP_ERROR_CODE (CNL_ADSP_FW_STATUS + 0x4) | ||
| 49 | |||
| 50 | #define CNL_INSTANCE_ID 0 | ||
| 51 | #define CNL_BASE_FW_MODULE_ID 0 | ||
| 52 | #define CNL_ADSP_FW_HDR_OFFSET 0x2000 | ||
| 53 | #define CNL_ROM_CTRL_DMA_ID 0x9 | ||
| 54 | |||
| 55 | static int cnl_prepare_fw(struct sst_dsp *ctx, const void *fwdata, u32 fwsize) | ||
| 56 | { | ||
| 57 | |||
| 58 | int ret, stream_tag; | ||
| 59 | |||
| 60 | stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); | ||
| 61 | if (stream_tag <= 0) { | ||
| 62 | dev_err(ctx->dev, "dma prepare failed: 0%#x\n", stream_tag); | ||
| 63 | return stream_tag; | ||
| 64 | } | ||
| 65 | |||
| 66 | ctx->dsp_ops.stream_tag = stream_tag; | ||
| 67 | memcpy(ctx->dmab.area, fwdata, fwsize); | ||
| 68 | |||
| 69 | /* purge FW request */ | ||
| 70 | sst_dsp_shim_write(ctx, CNL_ADSP_REG_HIPCIDR, | ||
| 71 | CNL_ADSP_REG_HIPCIDR_BUSY | (CNL_IPC_PURGE | | ||
| 72 | ((stream_tag - 1) << CNL_ROM_CTRL_DMA_ID))); | ||
| 73 | |||
| 74 | ret = cnl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); | ||
| 75 | if (ret < 0) { | ||
| 76 | dev_err(ctx->dev, "dsp boot core failed ret: %d\n", ret); | ||
| 77 | ret = -EIO; | ||
| 78 | goto base_fw_load_failed; | ||
| 79 | } | ||
| 80 | |||
| 81 | /* enable interrupt */ | ||
| 82 | cnl_ipc_int_enable(ctx); | ||
| 83 | cnl_ipc_op_int_enable(ctx); | ||
| 84 | |||
| 85 | ret = sst_dsp_register_poll(ctx, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK, | ||
| 86 | CNL_FW_ROM_INIT, CNL_INIT_TIMEOUT, | ||
| 87 | "rom load"); | ||
| 88 | if (ret < 0) { | ||
| 89 | dev_err(ctx->dev, "rom init timeout, ret: %d\n", ret); | ||
| 90 | goto base_fw_load_failed; | ||
| 91 | } | ||
| 92 | |||
| 93 | return 0; | ||
| 94 | |||
| 95 | base_fw_load_failed: | ||
| 96 | ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); | ||
| 97 | cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); | ||
| 98 | |||
| 99 | return ret; | ||
| 100 | } | ||
| 101 | |||
| 102 | static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) | ||
| 103 | { | ||
| 104 | int ret; | ||
| 105 | |||
| 106 | ctx->dsp_ops.trigger(ctx->dev, true, ctx->dsp_ops.stream_tag); | ||
| 107 | ret = sst_dsp_register_poll(ctx, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK, | ||
| 108 | CNL_FW_INIT, CNL_BASEFW_TIMEOUT, | ||
| 109 | "firmware boot"); | ||
| 110 | |||
| 111 | ctx->dsp_ops.trigger(ctx->dev, false, ctx->dsp_ops.stream_tag); | ||
| 112 | ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, ctx->dsp_ops.stream_tag); | ||
| 113 | |||
| 114 | return ret; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int cnl_load_base_firmware(struct sst_dsp *ctx) | ||
| 118 | { | ||
| 119 | struct firmware stripped_fw; | ||
| 120 | struct skl_sst *cnl = ctx->thread_context; | ||
| 121 | int ret; | ||
| 122 | |||
| 123 | if (!ctx->fw) { | ||
| 124 | ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); | ||
| 125 | if (ret < 0) { | ||
| 126 | dev_err(ctx->dev, "request firmware failed: %d\n", ret); | ||
| 127 | goto cnl_load_base_firmware_failed; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | /* parse uuids if first boot */ | ||
| 132 | if (cnl->is_first_boot) { | ||
| 133 | ret = snd_skl_parse_uuids(ctx, ctx->fw, | ||
| 134 | CNL_ADSP_FW_HDR_OFFSET, 0); | ||
| 135 | if (ret < 0) | ||
| 136 | goto cnl_load_base_firmware_failed; | ||
| 137 | } | ||
| 138 | |||
| 139 | stripped_fw.data = ctx->fw->data; | ||
| 140 | stripped_fw.size = ctx->fw->size; | ||
| 141 | skl_dsp_strip_extended_manifest(&stripped_fw); | ||
| 142 | |||
| 143 | ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); | ||
| 144 | if (ret < 0) { | ||
| 145 | dev_err(ctx->dev, "prepare firmware failed: %d\n", ret); | ||
| 146 | goto cnl_load_base_firmware_failed; | ||
| 147 | } | ||
| 148 | |||
| 149 | ret = sst_transfer_fw_host_dma(ctx); | ||
| 150 | if (ret < 0) { | ||
| 151 | dev_err(ctx->dev, "transfer firmware failed: %d\n", ret); | ||
| 152 | cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); | ||
| 153 | goto cnl_load_base_firmware_failed; | ||
| 154 | } | ||
| 155 | |||
| 156 | ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete, | ||
| 157 | msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); | ||
| 158 | if (ret == 0) { | ||
| 159 | dev_err(ctx->dev, "FW ready timed-out\n"); | ||
| 160 | cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); | ||
| 161 | ret = -EIO; | ||
| 162 | goto cnl_load_base_firmware_failed; | ||
| 163 | } | ||
| 164 | |||
| 165 | cnl->fw_loaded = true; | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | |||
| 169 | cnl_load_base_firmware_failed: | ||
| 170 | release_firmware(ctx->fw); | ||
| 171 | ctx->fw = NULL; | ||
| 172 | |||
| 173 | return ret; | ||
| 174 | } | ||
| 175 | |||
| 176 | static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) | ||
| 177 | { | ||
| 178 | struct skl_sst *cnl = ctx->thread_context; | ||
| 179 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); | ||
| 180 | struct skl_ipc_dxstate_info dx; | ||
| 181 | int ret; | ||
| 182 | |||
| 183 | if (!cnl->fw_loaded) { | ||
| 184 | cnl->boot_complete = false; | ||
| 185 | ret = cnl_load_base_firmware(ctx); | ||
| 186 | if (ret < 0) { | ||
| 187 | dev_err(ctx->dev, "fw reload failed: %d\n", ret); | ||
| 188 | return ret; | ||
| 189 | } | ||
| 190 | |||
| 191 | cnl->cores.state[core_id] = SKL_DSP_RUNNING; | ||
| 192 | return ret; | ||
| 193 | } | ||
| 194 | |||
| 195 | ret = cnl_dsp_enable_core(ctx, core_mask); | ||
| 196 | if (ret < 0) { | ||
| 197 | dev_err(ctx->dev, "enable dsp core %d failed: %d\n", | ||
| 198 | core_id, ret); | ||
| 199 | goto err; | ||
| 200 | } | ||
| 201 | |||
| 202 | if (core_id == SKL_DSP_CORE0_ID) { | ||
| 203 | /* enable interrupt */ | ||
| 204 | cnl_ipc_int_enable(ctx); | ||
| 205 | cnl_ipc_op_int_enable(ctx); | ||
| 206 | cnl->boot_complete = false; | ||
| 207 | |||
| 208 | ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete, | ||
| 209 | msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); | ||
| 210 | if (ret == 0) { | ||
| 211 | dev_err(ctx->dev, | ||
| 212 | "dsp boot timeout, status=%#x error=%#x\n", | ||
| 213 | sst_dsp_shim_read(ctx, CNL_ADSP_FW_STATUS), | ||
| 214 | sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE)); | ||
| 215 | goto err; | ||
| 216 | } | ||
| 217 | } else { | ||
| 218 | dx.core_mask = core_mask; | ||
| 219 | dx.dx_mask = core_mask; | ||
| 220 | |||
| 221 | ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID, | ||
| 222 | CNL_BASE_FW_MODULE_ID, &dx); | ||
| 223 | if (ret < 0) { | ||
| 224 | dev_err(ctx->dev, "set_dx failed, core: %d ret: %d\n", | ||
| 225 | core_id, ret); | ||
| 226 | goto err; | ||
| 227 | } | ||
| 228 | } | ||
| 229 | cnl->cores.state[core_id] = SKL_DSP_RUNNING; | ||
| 230 | |||
| 231 | return 0; | ||
| 232 | err: | ||
| 233 | cnl_dsp_disable_core(ctx, core_mask); | ||
| 234 | |||
| 235 | return ret; | ||
| 236 | } | ||
| 237 | |||
| 238 | static int cnl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) | ||
| 239 | { | ||
| 240 | struct skl_sst *cnl = ctx->thread_context; | ||
| 241 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); | ||
| 242 | struct skl_ipc_dxstate_info dx; | ||
| 243 | int ret; | ||
| 244 | |||
| 245 | dx.core_mask = core_mask; | ||
| 246 | dx.dx_mask = SKL_IPC_D3_MASK; | ||
| 247 | |||
| 248 | ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID, | ||
| 249 | CNL_BASE_FW_MODULE_ID, &dx); | ||
| 250 | if (ret < 0) { | ||
| 251 | dev_err(ctx->dev, | ||
| 252 | "dsp core %d to d3 failed; continue reset\n", | ||
| 253 | core_id); | ||
| 254 | cnl->fw_loaded = false; | ||
| 255 | } | ||
| 256 | |||
| 257 | /* disable interrupts if core 0 */ | ||
| 258 | if (core_id == SKL_DSP_CORE0_ID) { | ||
| 259 | skl_ipc_op_int_disable(ctx); | ||
| 260 | skl_ipc_int_disable(ctx); | ||
| 261 | } | ||
| 262 | |||
| 263 | ret = cnl_dsp_disable_core(ctx, core_mask); | ||
| 264 | if (ret < 0) { | ||
| 265 | dev_err(ctx->dev, "disable dsp core %d failed: %d\n", | ||
| 266 | core_id, ret); | ||
| 267 | return ret; | ||
| 268 | } | ||
| 269 | |||
| 270 | cnl->cores.state[core_id] = SKL_DSP_RESET; | ||
| 271 | |||
| 272 | return ret; | ||
| 273 | } | ||
| 274 | |||
| 275 | static unsigned int cnl_get_errno(struct sst_dsp *ctx) | ||
| 276 | { | ||
| 277 | return sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE); | ||
| 278 | } | ||
| 279 | |||
| 280 | static const struct skl_dsp_fw_ops cnl_fw_ops = { | ||
| 281 | .set_state_D0 = cnl_set_dsp_D0, | ||
| 282 | .set_state_D3 = cnl_set_dsp_D3, | ||
| 283 | .load_fw = cnl_load_base_firmware, | ||
| 284 | .get_fw_errcode = cnl_get_errno, | ||
| 285 | }; | ||
| 286 | |||
| 287 | static struct sst_ops cnl_ops = { | ||
| 288 | .irq_handler = cnl_dsp_sst_interrupt, | ||
| 289 | .write = sst_shim32_write, | ||
| 290 | .read = sst_shim32_read, | ||
| 291 | .ram_read = sst_memcpy_fromio_32, | ||
| 292 | .ram_write = sst_memcpy_toio_32, | ||
| 293 | .free = cnl_dsp_free, | ||
| 294 | }; | ||
| 295 | |||
| 296 | #define CNL_IPC_GLB_NOTIFY_RSP_SHIFT 29 | ||
| 297 | #define CNL_IPC_GLB_NOTIFY_RSP_MASK 0x1 | ||
| 298 | #define CNL_IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> CNL_IPC_GLB_NOTIFY_RSP_SHIFT) \ | ||
| 299 | & CNL_IPC_GLB_NOTIFY_RSP_MASK) | ||
| 300 | |||
| 301 | static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context) | ||
| 302 | { | ||
| 303 | struct sst_dsp *dsp = context; | ||
| 304 | struct skl_sst *cnl = sst_dsp_get_thread_context(dsp); | ||
| 305 | struct sst_generic_ipc *ipc = &cnl->ipc; | ||
| 306 | struct skl_ipc_header header = {0}; | ||
| 307 | u32 hipcida, hipctdr, hipctdd; | ||
| 308 | int ipc_irq = 0; | ||
| 309 | |||
| 310 | /* here we handle ipc interrupts only */ | ||
| 311 | if (!(dsp->intr_status & CNL_ADSPIS_IPC)) | ||
| 312 | return IRQ_NONE; | ||
| 313 | |||
| 314 | hipcida = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDA); | ||
| 315 | hipctdr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDR); | ||
| 316 | |||
| 317 | /* reply message from dsp */ | ||
| 318 | if (hipcida & CNL_ADSP_REG_HIPCIDA_DONE) { | ||
| 319 | sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL, | ||
| 320 | CNL_ADSP_REG_HIPCCTL_DONE, 0); | ||
| 321 | |||
| 322 | /* clear done bit - tell dsp operation is complete */ | ||
| 323 | sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCIDA, | ||
| 324 | CNL_ADSP_REG_HIPCIDA_DONE, CNL_ADSP_REG_HIPCIDA_DONE); | ||
| 325 | |||
| 326 | ipc_irq = 1; | ||
| 327 | |||
| 328 | /* unmask done interrupt */ | ||
| 329 | sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL, | ||
| 330 | CNL_ADSP_REG_HIPCCTL_DONE, CNL_ADSP_REG_HIPCCTL_DONE); | ||
| 331 | } | ||
| 332 | |||
| 333 | /* new message from dsp */ | ||
| 334 | if (hipctdr & CNL_ADSP_REG_HIPCTDR_BUSY) { | ||
| 335 | hipctdd = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDD); | ||
| 336 | header.primary = hipctdr; | ||
| 337 | header.extension = hipctdd; | ||
| 338 | dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x", | ||
| 339 | header.primary); | ||
| 340 | dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x", | ||
| 341 | header.extension); | ||
| 342 | |||
| 343 | if (CNL_IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) { | ||
| 344 | /* Handle Immediate reply from DSP Core */ | ||
| 345 | skl_ipc_process_reply(ipc, header); | ||
| 346 | } else { | ||
| 347 | dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n"); | ||
| 348 | skl_ipc_process_notification(ipc, header); | ||
| 349 | } | ||
| 350 | /* clear busy interrupt */ | ||
| 351 | sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDR, | ||
| 352 | CNL_ADSP_REG_HIPCTDR_BUSY, CNL_ADSP_REG_HIPCTDR_BUSY); | ||
| 353 | |||
| 354 | /* set done bit to ack dsp */ | ||
| 355 | sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDA, | ||
| 356 | CNL_ADSP_REG_HIPCTDA_DONE, CNL_ADSP_REG_HIPCTDA_DONE); | ||
| 357 | ipc_irq = 1; | ||
| 358 | } | ||
| 359 | |||
| 360 | if (ipc_irq == 0) | ||
| 361 | return IRQ_NONE; | ||
| 362 | |||
| 363 | cnl_ipc_int_enable(dsp); | ||
| 364 | |||
| 365 | /* continue to send any remaining messages */ | ||
| 366 | schedule_work(&ipc->kwork); | ||
| 367 | |||
| 368 | return IRQ_HANDLED; | ||
| 369 | } | ||
| 370 | |||
| 371 | static struct sst_dsp_device cnl_dev = { | ||
| 372 | .thread = cnl_dsp_irq_thread_handler, | ||
| 373 | .ops = &cnl_ops, | ||
| 374 | }; | ||
| 375 | |||
| 376 | static void cnl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) | ||
| 377 | { | ||
| 378 | struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); | ||
| 379 | |||
| 380 | if (msg->tx_size) | ||
| 381 | sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); | ||
| 382 | sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDD, | ||
| 383 | header->extension); | ||
| 384 | sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDR, | ||
| 385 | header->primary | CNL_ADSP_REG_HIPCIDR_BUSY); | ||
| 386 | } | ||
| 387 | |||
| 388 | static bool cnl_ipc_is_dsp_busy(struct sst_dsp *dsp) | ||
| 389 | { | ||
| 390 | u32 hipcidr; | ||
| 391 | |||
| 392 | hipcidr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDR); | ||
| 393 | |||
| 394 | return (hipcidr & CNL_ADSP_REG_HIPCIDR_BUSY); | ||
| 395 | } | ||
| 396 | |||
| 397 | static int cnl_ipc_init(struct device *dev, struct skl_sst *cnl) | ||
| 398 | { | ||
| 399 | struct sst_generic_ipc *ipc; | ||
| 400 | int err; | ||
| 401 | |||
| 402 | ipc = &cnl->ipc; | ||
| 403 | ipc->dsp = cnl->dsp; | ||
| 404 | ipc->dev = dev; | ||
| 405 | |||
| 406 | ipc->tx_data_max_size = CNL_ADSP_W1_SZ; | ||
| 407 | ipc->rx_data_max_size = CNL_ADSP_W0_UP_SZ; | ||
| 408 | |||
| 409 | err = sst_ipc_init(ipc); | ||
| 410 | if (err) | ||
| 411 | return err; | ||
| 412 | |||
| 413 | /* | ||
| 414 | * overriding tx_msg and is_dsp_busy since | ||
| 415 | * ipc registers are different for cnl | ||
| 416 | */ | ||
| 417 | ipc->ops.tx_msg = cnl_ipc_tx_msg; | ||
| 418 | ipc->ops.tx_data_copy = skl_ipc_tx_data_copy; | ||
| 419 | ipc->ops.is_dsp_busy = cnl_ipc_is_dsp_busy; | ||
| 420 | |||
| 421 | return 0; | ||
| 422 | } | ||
| 423 | |||
| 424 | int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | ||
| 425 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, | ||
| 426 | struct skl_sst **dsp) | ||
| 427 | { | ||
| 428 | struct skl_sst *cnl; | ||
| 429 | struct sst_dsp *sst; | ||
| 430 | int ret; | ||
| 431 | |||
| 432 | ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &cnl_dev); | ||
| 433 | if (ret < 0) { | ||
| 434 | dev_err(dev, "%s: no device\n", __func__); | ||
| 435 | return ret; | ||
| 436 | } | ||
| 437 | |||
| 438 | cnl = *dsp; | ||
| 439 | sst = cnl->dsp; | ||
| 440 | sst->fw_ops = cnl_fw_ops; | ||
| 441 | sst->addr.lpe = mmio_base; | ||
| 442 | sst->addr.shim = mmio_base; | ||
| 443 | sst->addr.sram0_base = CNL_ADSP_SRAM0_BASE; | ||
| 444 | sst->addr.sram1_base = CNL_ADSP_SRAM1_BASE; | ||
| 445 | sst->addr.w0_stat_sz = CNL_ADSP_W0_STAT_SZ; | ||
| 446 | sst->addr.w0_up_sz = CNL_ADSP_W0_UP_SZ; | ||
| 447 | |||
| 448 | sst_dsp_mailbox_init(sst, (CNL_ADSP_SRAM0_BASE + CNL_ADSP_W0_STAT_SZ), | ||
| 449 | CNL_ADSP_W0_UP_SZ, CNL_ADSP_SRAM1_BASE, | ||
| 450 | CNL_ADSP_W1_SZ); | ||
| 451 | |||
| 452 | ret = cnl_ipc_init(dev, cnl); | ||
| 453 | if (ret) { | ||
| 454 | skl_dsp_free(sst); | ||
| 455 | return ret; | ||
| 456 | } | ||
| 457 | |||
| 458 | cnl->boot_complete = false; | ||
| 459 | init_waitqueue_head(&cnl->boot_wait); | ||
| 460 | |||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | EXPORT_SYMBOL_GPL(cnl_sst_dsp_init); | ||
| 464 | |||
| 465 | int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx) | ||
| 466 | { | ||
| 467 | int ret; | ||
| 468 | struct sst_dsp *sst = ctx->dsp; | ||
| 469 | |||
| 470 | ret = ctx->dsp->fw_ops.load_fw(sst); | ||
| 471 | if (ret < 0) { | ||
| 472 | dev_err(dev, "load base fw failed: %d", ret); | ||
| 473 | return ret; | ||
| 474 | } | ||
| 475 | |||
| 476 | skl_dsp_init_core_state(sst); | ||
| 477 | |||
| 478 | ctx->is_first_boot = false; | ||
| 479 | |||
| 480 | return 0; | ||
| 481 | } | ||
| 482 | EXPORT_SYMBOL_GPL(cnl_sst_init_fw); | ||
| 483 | |||
| 484 | void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) | ||
| 485 | { | ||
| 486 | if (ctx->dsp->fw) | ||
| 487 | release_firmware(ctx->dsp->fw); | ||
| 488 | |||
| 489 | skl_freeup_uuid_list(ctx); | ||
| 490 | cnl_ipc_free(&ctx->ipc); | ||
| 491 | |||
| 492 | ctx->dsp->ops->free(ctx->dsp); | ||
| 493 | } | ||
| 494 | EXPORT_SYMBOL_GPL(cnl_sst_dsp_cleanup); | ||
| 495 | |||
| 496 | MODULE_LICENSE("GPL v2"); | ||
| 497 | MODULE_DESCRIPTION("Intel Cannonlake IPC driver"); | ||
| @@ -22,6 +22,7 @@ · 21 unmodified lines | |||
| 22 | #include <sound/core.h> | 22 | #include <sound/core.h> |
| 23 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
| 24 | #include "skl-sst-dsp.h" | 24 | #include "skl-sst-dsp.h" |
| 25 | #include "cnl-sst-dsp.h" | ||
| 25 | #include "skl-sst-ipc.h" | 26 | #include "skl-sst-ipc.h" |
| 26 | #include "skl.h" | 27 | #include "skl.h" |
| 27 | #include "../common/sst-dsp.h" | 28 | #include "../common/sst-dsp.h" |
| @@ -201,6 +202,7 @@ static struct skl_dsp_loader_ops bxt_get_loader_ops(void) · 173 unmodified lines | |||
| 201 | static const struct skl_dsp_ops dsp_ops[] = { | 202 | static const struct skl_dsp_ops dsp_ops[] = { |
| 202 | { | 203 | { |
| 203 | .id = 0x9d70, | 204 | .id = 0x9d70, |
| 205 | .num_cores = 2, | ||
| 204 | .loader_ops = skl_get_loader_ops, | 206 | .loader_ops = skl_get_loader_ops, |
| 205 | .init = skl_sst_dsp_init, | 207 | .init = skl_sst_dsp_init, |
| 206 | .init_fw = skl_sst_init_fw, | 208 | .init_fw = skl_sst_init_fw, |
| @@ -208,6 +210,7 @@ static const struct skl_dsp_ops dsp_ops[] = { · 1 unmodified line | |||
| 208 | }, | 210 | }, |
| 209 | { | 211 | { |
| 210 | .id = 0x9d71, | 212 | .id = 0x9d71, |
| 213 | .num_cores = 2, | ||
| 211 | .loader_ops = skl_get_loader_ops, | 214 | .loader_ops = skl_get_loader_ops, |
| 212 | .init = kbl_sst_dsp_init, | 215 | .init = kbl_sst_dsp_init, |
| 213 | .init_fw = skl_sst_init_fw, | 216 | .init_fw = skl_sst_init_fw, |
| @@ -215,6 +218,7 @@ static const struct skl_dsp_ops dsp_ops[] = { · 1 unmodified line | |||
| 215 | }, | 218 | }, |
| 216 | { | 219 | { |
| 217 | .id = 0x5a98, | 220 | .id = 0x5a98, |
| 221 | .num_cores = 2, | ||
| 218 | .loader_ops = bxt_get_loader_ops, | 222 | .loader_ops = bxt_get_loader_ops, |
| 219 | .init = bxt_sst_dsp_init, | 223 | .init = bxt_sst_dsp_init, |
| 220 | .init_fw = bxt_sst_init_fw, | 224 | .init_fw = bxt_sst_init_fw, |
| @@ -222,11 +226,20 @@ static const struct skl_dsp_ops dsp_ops[] = { · 1 unmodified line | |||
| 222 | }, | 226 | }, |
| 223 | { | 227 | { |
| 224 | .id = 0x3198, | 228 | .id = 0x3198, |
| 229 | .num_cores = 2, | ||
| 225 | .loader_ops = bxt_get_loader_ops, | 230 | .loader_ops = bxt_get_loader_ops, |
| 226 | .init = bxt_sst_dsp_init, | 231 | .init = bxt_sst_dsp_init, |
| 227 | .init_fw = bxt_sst_init_fw, | 232 | .init_fw = bxt_sst_init_fw, |
| 228 | .cleanup = bxt_sst_dsp_cleanup | 233 | .cleanup = bxt_sst_dsp_cleanup |
| 229 | }, | 234 | }, |
| 235 | { | ||
| 236 | .id = 0x9dc8, | ||
| 237 | .num_cores = 4, | ||
| 238 | .loader_ops = bxt_get_loader_ops, | ||
| 239 | .init = cnl_sst_dsp_init, | ||
| 240 | .init_fw = cnl_sst_init_fw, | ||
| 241 | .cleanup = cnl_sst_dsp_cleanup | ||
| 242 | }, | ||
| 230 | }; | 243 | }; |
| 231 | 244 | ||
| 232 | const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) | 245 | const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) |
| @@ -249,6 +262,7 @@ int skl_init_dsp(struct skl *skl) · 16 unmodified lines | |||
| 249 | struct skl_dsp_loader_ops loader_ops; | 262 | struct skl_dsp_loader_ops loader_ops; |
| 250 | int irq = bus->irq; | 263 | int irq = bus->irq; |
| 251 | const struct skl_dsp_ops *ops; | 264 | const struct skl_dsp_ops *ops; |
| 265 | struct skl_dsp_cores *cores; | ||
| 252 | int ret; | 266 | int ret; |
| 253 | 267 | ||
| 254 | /* enable ppcap interrupt */ | 268 | /* enable ppcap interrupt */ |
| @@ -263,8 +277,10 @@ int skl_init_dsp(struct skl *skl) · 8 unmodified lines | |||
| 263 | } | 277 | } |
| 264 | 278 | ||
| 265 | ops = skl_get_dsp_ops(skl->pci->device); | 279 | ops = skl_get_dsp_ops(skl->pci->device); |
| 266 | if (!ops) | 280 | if (!ops) { |
| 267 | return -EIO; | 281 | ret = -EIO; |
| 282 | goto unmap_mmio; | ||
| 283 | } | ||
| 268 | 284 | ||
| 269 | loader_ops = ops->loader_ops(); | 285 | loader_ops = ops->loader_ops(); |
| 270 | ret = ops->init(bus->dev, mmio_base, irq, | 286 | ret = ops->init(bus->dev, mmio_base, irq, |
| @@ -272,11 +288,35 @@ int skl_init_dsp(struct skl *skl) · 1 unmodified line | |||
| 272 | &skl->skl_sst); | 288 | &skl->skl_sst); |
| 273 | 289 | ||
| 274 | if (ret < 0) | 290 | if (ret < 0) |
| 275 | return ret; | 291 | goto unmap_mmio; |
| 276 | 292 | ||
| 277 | skl->skl_sst->dsp_ops = ops; | 293 | skl->skl_sst->dsp_ops = ops; |
| 294 | cores = &skl->skl_sst->cores; | ||
| 295 | cores->count = ops->num_cores; | ||
| 296 | |||
| 297 | cores->state = kcalloc(cores->count, sizeof(*cores->state), GFP_KERNEL); | ||
| 298 | if (!cores->state) { | ||
| 299 | ret = -ENOMEM; | ||
| 300 | goto unmap_mmio; | ||
| 301 | } | ||
| 302 | |||
| 303 | cores->usage_count = kcalloc(cores->count, sizeof(*cores->usage_count), | ||
| 304 | GFP_KERNEL); | ||
| 305 | if (!cores->usage_count) { | ||
| 306 | ret = -ENOMEM; | ||
| 307 | goto free_core_state; | ||
| 308 | } | ||
| 309 | |||
| 278 | dev_dbg(bus->dev, "dsp registration status=%d\n", ret); | 310 | dev_dbg(bus->dev, "dsp registration status=%d\n", ret); |
| 279 | 311 | ||
| 312 | return 0; | ||
| 313 | |||
| 314 | free_core_state: | ||
| 315 | kfree(cores->state); | ||
| 316 | |||
| 317 | unmap_mmio: | ||
| 318 | iounmap(mmio_base); | ||
| 319 | |||
| 280 | return ret; | 320 | return ret; |
| 281 | } | 321 | } |
| 282 | 322 | ||
| @@ -291,6 +331,9 @@ int skl_free_dsp(struct skl *skl) · 8 unmodified lines | |||
| 291 | 331 | ||
| 292 | ctx->dsp_ops->cleanup(bus->dev, ctx); | 332 | ctx->dsp_ops->cleanup(bus->dev, ctx); |
| 293 | 333 | ||
| 334 | kfree(ctx->cores.state); | ||
| 335 | kfree(ctx->cores.usage_count); | ||
| 336 | |||
| 294 | if (ctx->dsp->addr.lpe) | 337 | if (ctx->dsp->addr.lpe) |
| 295 | iounmap(ctx->dsp->addr.lpe); | 338 | iounmap(ctx->dsp->addr.lpe); |
| 296 | 339 | ||
| @@ -400,9 +443,12 @@ static void skl_set_base_module_format(struct skl_sst *ctx, · 103 unmodified lines | |||
| 400 | struct skl_module_cfg *mconfig, | 443 | struct skl_module_cfg *mconfig, |
| 401 | struct skl_base_cfg *base_cfg) | 444 | struct skl_base_cfg *base_cfg) |
| 402 | { | 445 | { |
| 403 | struct skl_module_fmt *format = &mconfig->in_fmt[0]; | 446 | struct skl_module *module = mconfig->module; |
| 447 | struct skl_module_res *res = &module->resources[mconfig->res_idx]; | ||
| 448 | struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx]; | ||
| 449 | struct skl_module_fmt *format = &fmt->inputs[0].fmt; | ||
| 404 | 450 | ||
| 405 | base_cfg->audio_fmt.number_of_channels = (u8)format->channels; | 451 | base_cfg->audio_fmt.number_of_channels = format->channels; |
| 406 | 452 | ||
| 407 | base_cfg->audio_fmt.s_freq = format->s_freq; | 453 | base_cfg->audio_fmt.s_freq = format->s_freq; |
| 408 | base_cfg->audio_fmt.bit_depth = format->bit_depth; | 454 | base_cfg->audio_fmt.bit_depth = format->bit_depth; |
| @@ -417,10 +463,10 @@ static void skl_set_base_module_format(struct skl_sst *ctx, · 8 unmodified lines | |||
| 417 | 463 | ||
| 418 | base_cfg->audio_fmt.interleaving = format->interleaving_style; | 464 | base_cfg->audio_fmt.interleaving = format->interleaving_style; |
| 419 | 465 | ||
| 420 | base_cfg->cps = mconfig->mcps; | 466 | base_cfg->cps = res->cps; |
| 421 | base_cfg->ibs = mconfig->ibs; | 467 | base_cfg->ibs = res->ibs; |
| 422 | base_cfg->obs = mconfig->obs; | 468 | base_cfg->obs = res->obs; |
| 423 | base_cfg->is_pages = mconfig->mem_pages; | 469 | base_cfg->is_pages = res->is_pages; |
| 424 | } | 470 | } |
| 425 | 471 | ||
| 426 | /* | 472 | /* |
| @@ -508,6 +554,9 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, · 81 unmodified lines | |||
| 508 | struct skl_cpr_cfg *cpr_mconfig) | 554 | struct skl_cpr_cfg *cpr_mconfig) |
| 509 | { | 555 | { |
| 510 | u32 dma_io_buf; | 556 | u32 dma_io_buf; |
| 557 | struct skl_module_res *res; | ||
| 558 | int res_idx = mconfig->res_idx; | ||
| 559 | struct skl *skl = get_skl_ctx(ctx->dev); | ||
| 511 | 560 | ||
| 512 | cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); | 561 | cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); |
| 513 | 562 | ||
| @@ -516,19 +565,27 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, · 2 unmodified lines | |||
| 516 | return; | 565 | return; |
| 517 | } | 566 | } |
| 518 | 567 | ||
| 568 | if (skl->nr_modules) { | ||
| 569 | res = &mconfig->module->resources[mconfig->res_idx]; | ||
| 570 | cpr_mconfig->gtw_cfg.dma_buffer_size = res->dma_buffer_size; | ||
| 571 | goto skip_buf_size_calc; | ||
| 572 | } else { | ||
| 573 | res = &mconfig->module->resources[res_idx]; | ||
| 574 | } | ||
| 575 | |||
| 519 | switch (mconfig->hw_conn_type) { | 576 | switch (mconfig->hw_conn_type) { |
| 520 | case SKL_CONN_SOURCE: | 577 | case SKL_CONN_SOURCE: |
| 521 | if (mconfig->dev_type == SKL_DEVICE_HDAHOST) | 578 | if (mconfig->dev_type == SKL_DEVICE_HDAHOST) |
| 522 | dma_io_buf = mconfig->ibs; | 579 | dma_io_buf = res->ibs; |
| 523 | else | 580 | else |
| 524 | dma_io_buf = mconfig->obs; | 581 | dma_io_buf = res->obs; |
| 525 | break; | 582 | break; |
| 526 | 583 | ||
| 527 | case SKL_CONN_SINK: | 584 | case SKL_CONN_SINK: |
| 528 | if (mconfig->dev_type == SKL_DEVICE_HDAHOST) | 585 | if (mconfig->dev_type == SKL_DEVICE_HDAHOST) |
| 529 | dma_io_buf = mconfig->obs; | 586 | dma_io_buf = res->obs; |
| 530 | else | 587 | else |
| 531 | dma_io_buf = mconfig->ibs; | 588 | dma_io_buf = res->ibs; |
| 532 | break; | 589 | break; |
| 533 | 590 | ||
| 534 | default: | 591 | default: |
| @@ -543,11 +600,12 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, · 8 unmodified lines | |||
| 543 | /* fallback to 2ms default value */ | 600 | /* fallback to 2ms default value */ |
| 544 | if (!cpr_mconfig->gtw_cfg.dma_buffer_size) { | 601 | if (!cpr_mconfig->gtw_cfg.dma_buffer_size) { |
| 545 | if (mconfig->hw_conn_type == SKL_CONN_SOURCE) | 602 | if (mconfig->hw_conn_type == SKL_CONN_SOURCE) |
| 546 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; | 603 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->obs; |
| 547 | else | 604 | else |
| 548 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; | 605 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->ibs; |
| 549 | } | 606 | } |
| 550 | 607 | ||
| 608 | skip_buf_size_calc: | ||
| 551 | cpr_mconfig->cpr_feature_mask = 0; | 609 | cpr_mconfig->cpr_feature_mask = 0; |
| 552 | cpr_mconfig->gtw_cfg.config_length = 0; | 610 | cpr_mconfig->gtw_cfg.config_length = 0; |
| 553 | 611 | ||
| @@ -595,7 +653,9 @@ static void skl_setup_out_format(struct skl_sst *ctx, · 41 unmodified lines | |||
| 595 | struct skl_module_cfg *mconfig, | 653 | struct skl_module_cfg *mconfig, |
| 596 | struct skl_audio_data_format *out_fmt) | 654 | struct skl_audio_data_format *out_fmt) |
| 597 | { | 655 | { |
| 598 | struct skl_module_fmt *format = &mconfig->out_fmt[0]; | 656 | struct skl_module *module = mconfig->module; |
| 657 | struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx]; | ||
| 658 | struct skl_module_fmt *format = &fmt->outputs[0].fmt; | ||
| 599 | 659 | ||
| 600 | out_fmt->number_of_channels = (u8)format->channels; | 660 | out_fmt->number_of_channels = (u8)format->channels; |
| 601 | out_fmt->s_freq = format->s_freq; | 661 | out_fmt->s_freq = format->s_freq; |
| @@ -620,7 +680,9 @@ static void skl_set_src_format(struct skl_sst *ctx, · 18 unmodified lines | |||
| 620 | struct skl_module_cfg *mconfig, | 680 | struct skl_module_cfg *mconfig, |
| 621 | struct skl_src_module_cfg *src_mconfig) | 681 | struct skl_src_module_cfg *src_mconfig) |
| 622 | { | 682 | { |
| 623 | struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; | 683 | struct skl_module *module = mconfig->module; |
| 684 | struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; | ||
| 685 | struct skl_module_fmt *fmt = &iface->outputs[0].fmt; | ||
| 624 | 686 | ||
| 625 | skl_set_base_module_format(ctx, mconfig, | 687 | skl_set_base_module_format(ctx, mconfig, |
| 626 | (struct skl_base_cfg *)src_mconfig); | 688 | (struct skl_base_cfg *)src_mconfig); |
| @@ -637,7 +699,9 @@ static void skl_set_updown_mixer_format(struct skl_sst *ctx, · 10 unmodified lines | |||
| 637 | struct skl_module_cfg *mconfig, | 699 | struct skl_module_cfg *mconfig, |
| 638 | struct skl_up_down_mixer_cfg *mixer_mconfig) | 700 | struct skl_up_down_mixer_cfg *mixer_mconfig) |
| 639 | { | 701 | { |
| 640 | struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; | 702 | struct skl_module *module = mconfig->module; |
| 703 | struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; | ||
| 704 | struct skl_module_fmt *fmt = &iface->outputs[0].fmt; | ||
| 641 | int i = 0; | 705 | int i = 0; |
| 642 | 706 | ||
| 643 | skl_set_base_module_format(ctx, mconfig, | 707 | skl_set_base_module_format(ctx, mconfig, |
| @@ -950,7 +1014,7 @@ static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg · 306 unmodified lines | |||
| 950 | { | 1014 | { |
| 951 | dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n", | 1015 | dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n", |
| 952 | __func__, src_module->id.module_id, src_module->id.pvt_id); | 1016 | __func__, src_module->id.module_id, src_module->id.pvt_id); |
| 953 | dev_dbg(ctx->dev, "%s: dst_module=%d dst_instacne=%d\n", __func__, | 1017 | dev_dbg(ctx->dev, "%s: dst_module=%d dst_instance=%d\n", __func__, |
| 954 | dst_module->id.module_id, dst_module->id.pvt_id); | 1018 | dst_module->id.module_id, dst_module->id.pvt_id); |
| 955 | 1019 | ||
| 956 | dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n", | 1020 | dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n", |
| @@ -970,8 +1034,8 @@ int skl_unbind_modules(struct skl_sst *ctx, · 13 unmodified lines | |||
| 970 | struct skl_ipc_bind_unbind_msg msg; | 1034 | struct skl_ipc_bind_unbind_msg msg; |
| 971 | struct skl_module_inst_id src_id = src_mcfg->id; | 1035 | struct skl_module_inst_id src_id = src_mcfg->id; |
| 972 | struct skl_module_inst_id dst_id = dst_mcfg->id; | 1036 | struct skl_module_inst_id dst_id = dst_mcfg->id; |
| 973 | int in_max = dst_mcfg->max_in_queue; | 1037 | int in_max = dst_mcfg->module->max_input_pins; |
| 974 | int out_max = src_mcfg->max_out_queue; | 1038 | int out_max = src_mcfg->module->max_output_pins; |
| 975 | int src_index, dst_index, src_pin_state, dst_pin_state; | 1039 | int src_index, dst_index, src_pin_state, dst_pin_state; |
| 976 | 1040 | ||
| 977 | skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); | 1041 | skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); |
| @@ -1019,6 +1083,21 @@ int skl_unbind_modules(struct skl_sst *ctx, · 41 unmodified lines | |||
| 1019 | return ret; | 1083 | return ret; |
| 1020 | } | 1084 | } |
| 1021 | 1085 | ||
| 1086 | static void fill_pin_params(struct skl_audio_data_format *pin_fmt, | ||
| 1087 | struct skl_module_fmt *format) | ||
| 1088 | { | ||
| 1089 | pin_fmt->number_of_channels = format->channels; | ||
| 1090 | pin_fmt->s_freq = format->s_freq; | ||
| 1091 | pin_fmt->bit_depth = format->bit_depth; | ||
| 1092 | pin_fmt->valid_bit_depth = format->valid_bit_depth; | ||
| 1093 | pin_fmt->ch_cfg = format->ch_cfg; | ||
| 1094 | pin_fmt->sample_type = format->sample_type; | ||
| 1095 | pin_fmt->channel_map = format->ch_map; | ||
| 1096 | pin_fmt->interleaving = format->interleaving_style; | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | #define CPR_SINK_FMT_PARAM_ID 2 | ||
| 1100 | |||
| 1022 | /* | 1101 | /* |
| 1023 | * Once a module is instantiated it need to be 'bind' with other modules in | 1102 | * Once a module is instantiated it need to be 'bind' with other modules in |
| 1024 | * the pipeline. For binding we need to find the module pins which are bind | 1103 | * the pipeline. For binding we need to find the module pins which are bind |
| @@ -1030,11 +1109,15 @@ int skl_bind_modules(struct skl_sst *ctx, · 5 unmodified lines | |||
| 1030 | struct skl_module_cfg *src_mcfg, | 1109 | struct skl_module_cfg *src_mcfg, |
| 1031 | struct skl_module_cfg *dst_mcfg) | 1110 | struct skl_module_cfg *dst_mcfg) |
| 1032 | { | 1111 | { |
| 1033 | int ret; | 1112 | int ret = 0; |
| 1034 | struct skl_ipc_bind_unbind_msg msg; | 1113 | struct skl_ipc_bind_unbind_msg msg; |
| 1035 | int in_max = dst_mcfg->max_in_queue; | 1114 | int in_max = dst_mcfg->module->max_input_pins; |
| 1036 | int out_max = src_mcfg->max_out_queue; | 1115 | int out_max = src_mcfg->module->max_output_pins; |
| 1037 | int src_index, dst_index; | 1116 | int src_index, dst_index; |
| 1117 | struct skl_module_fmt *format; | ||
| 1118 | struct skl_cpr_pin_fmt pin_fmt; | ||
| 1119 | struct skl_module *module; | ||
| 1120 | struct skl_module_iface *fmt; | ||
| 1038 | 1121 | ||
| 1039 | skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); | 1122 | skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); |
| 1040 | 1123 | ||
| @@ -1053,6 +1136,29 @@ int skl_bind_modules(struct skl_sst *ctx, · 12 unmodified lines | |||
| 1053 | return -EINVAL; | 1136 | return -EINVAL; |
| 1054 | } | 1137 | } |
| 1055 | 1138 | ||
| 1139 | /* | ||
| 1140 | * Copier module requires the separate large_config_set_ipc to | ||
| 1141 | * configure the pins other than 0 | ||
| 1142 | */ | ||
| 1143 | if (src_mcfg->m_type == SKL_MODULE_TYPE_COPIER && src_index > 0) { | ||
| 1144 | pin_fmt.sink_id = src_index; | ||
| 1145 | module = src_mcfg->module; | ||
| 1146 | fmt = &module->formats[src_mcfg->fmt_idx]; | ||
| 1147 | |||
| 1148 | /* Input fmt is same as that of src module input cfg */ | ||
| 1149 | format = &fmt->inputs[0].fmt; | ||
| 1150 | fill_pin_params(&(pin_fmt.src_fmt), format); | ||
| 1151 | |||
| 1152 | format = &fmt->outputs[src_index].fmt; | ||
| 1153 | fill_pin_params(&(pin_fmt.dst_fmt), format); | ||
| 1154 | ret = skl_set_module_params(ctx, (void *)&pin_fmt, | ||
| 1155 | sizeof(struct skl_cpr_pin_fmt), | ||
| 1156 | CPR_SINK_FMT_PARAM_ID, src_mcfg); | ||
| 1157 | |||
| 1158 | if (ret < 0) | ||
| 1159 | goto out; | ||
| 1160 | } | ||
| 1161 | |||
| 1056 | msg.dst_queue = dst_index; | 1162 | msg.dst_queue = dst_index; |
| 1057 | 1163 | ||
| 1058 | dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n", | 1164 | dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n", |
| @@ -1070,11 +1176,12 @@ int skl_bind_modules(struct skl_sst *ctx, · 11 unmodified lines | |||
| 1070 | src_mcfg->m_state = SKL_MODULE_BIND_DONE; | 1176 | src_mcfg->m_state = SKL_MODULE_BIND_DONE; |
| 1071 | src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE; | 1177 | src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE; |
| 1072 | dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE; | 1178 | dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE; |
| 1073 | } else { | 1179 | return ret; |
| 1074 | /* error case , if IPC fails, clear the queue index */ | ||
| 1075 | skl_free_queue(src_mcfg->m_out_pin, src_index); | ||
| 1076 | skl_free_queue(dst_mcfg->m_in_pin, dst_index); | ||
| 1077 | } | 1180 | } |
| 1181 | out: | ||
| 1182 | /* error case , if IPC fails, clear the queue index */ | ||
| 1183 | skl_free_queue(src_mcfg->m_out_pin, src_index); | ||
| 1184 | skl_free_queue(dst_mcfg->m_in_pin, dst_index); | ||
| 1078 | 1185 | ||
| 1079 | return ret; | 1186 | return ret; |
| 1080 | } | 1187 | } |
| @@ -33,7 +33,7 @@ · 32 unmodified lines | |||
| 33 | #define HDA_STEREO 2 | 33 | #define HDA_STEREO 2 |
| 34 | #define HDA_QUAD 4 | 34 | #define HDA_QUAD 4 |
| 35 | 35 | ||
| 36 | static struct snd_pcm_hardware azx_pcm_hw = { | 36 | static const struct snd_pcm_hardware azx_pcm_hw = { |
| 37 | .info = (SNDRV_PCM_INFO_MMAP | | 37 | .info = (SNDRV_PCM_INFO_MMAP | |
| 38 | SNDRV_PCM_INFO_INTERLEAVED | | 38 | SNDRV_PCM_INFO_INTERLEAVED | |
| 39 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 39 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
| @@ -628,7 +628,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream, · 588 unmodified lines | |||
| 628 | return 0; | 628 | return 0; |
| 629 | } | 629 | } |
| 630 | 630 | ||
| 631 | static struct snd_soc_dai_ops skl_pcm_dai_ops = { | 631 | static const struct snd_soc_dai_ops skl_pcm_dai_ops = { |
| 632 | .startup = skl_pcm_open, | 632 | .startup = skl_pcm_open, |
| 633 | .shutdown = skl_pcm_close, | 633 | .shutdown = skl_pcm_close, |
| 634 | .prepare = skl_pcm_prepare, | 634 | .prepare = skl_pcm_prepare, |
| @@ -637,15 +637,15 @@ static struct snd_soc_dai_ops skl_pcm_dai_ops = { · 2 unmodified lines | |||
| 637 | .trigger = skl_pcm_trigger, | 637 | .trigger = skl_pcm_trigger, |
| 638 | }; | 638 | }; |
| 639 | 639 | ||
| 640 | static struct snd_soc_dai_ops skl_dmic_dai_ops = { | 640 | static const struct snd_soc_dai_ops skl_dmic_dai_ops = { |
| 641 | .hw_params = skl_be_hw_params, | 641 | .hw_params = skl_be_hw_params, |
| 642 | }; | 642 | }; |
| 643 | 643 | ||
| 644 | static struct snd_soc_dai_ops skl_be_ssp_dai_ops = { | 644 | static const struct snd_soc_dai_ops skl_be_ssp_dai_ops = { |
| 645 | .hw_params = skl_be_hw_params, | 645 | .hw_params = skl_be_hw_params, |
| 646 | }; | 646 | }; |
| 647 | 647 | ||
| 648 | static struct snd_soc_dai_ops skl_link_dai_ops = { | 648 | static const struct snd_soc_dai_ops skl_link_dai_ops = { |
| 649 | .prepare = skl_link_pcm_prepare, | 649 | .prepare = skl_link_pcm_prepare, |
| 650 | .hw_params = skl_link_hw_params, | 650 | .hw_params = skl_link_hw_params, |
| 651 | .hw_free = skl_link_hw_free, | 651 | .hw_free = skl_link_hw_free, |
| @@ -674,6 +674,32 @@ static struct snd_soc_dai_driver skl_platform_dai[] = { · 22 unmodified lines | |||
| 674 | .sig_bits = 32, | 674 | .sig_bits = 32, |
| 675 | }, | 675 | }, |
| 676 | }, | 676 | }, |
| 677 | { | ||
| 678 | .name = "System Pin2", | ||
| 679 | .ops = &skl_pcm_dai_ops, | ||
| 680 | .playback = { | ||
| 681 | .stream_name = "Headset Playback", | ||
| 682 | .channels_min = HDA_MONO, | ||
| 683 | .channels_max = HDA_STEREO, | ||
| 684 | .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | | ||
| 685 | SNDRV_PCM_RATE_8000, | ||
| 686 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
| 687 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, | ||
| 688 | }, | ||
| 689 | }, | ||
| 690 | { | ||
| 691 | .name = "Echoref Pin", | ||
| 692 | .ops = &skl_pcm_dai_ops, | ||
| 693 | .capture = { | ||
| 694 | .stream_name = "Echoreference Capture", | ||
| 695 | .channels_min = HDA_STEREO, | ||
| 696 | .channels_max = HDA_STEREO, | ||
| 697 | .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | | ||
| 698 | SNDRV_PCM_RATE_8000, | ||
| 699 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
| 700 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, | ||
| 701 | }, | ||
| 702 | }, | ||
| 677 | { | 703 | { |
| 678 | .name = "Reference Pin", | 704 | .name = "Reference Pin", |
| 679 | .ops = &skl_pcm_dai_ops, | 705 | .ops = &skl_pcm_dai_ops, |
| @@ -1194,8 +1220,11 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd) · 514 unmodified lines | |||
| 1194 | static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) | 1220 | static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) |
| 1195 | { | 1221 | { |
| 1196 | struct skl_sst *ctx = skl->skl_sst; | 1222 | struct skl_sst *ctx = skl->skl_sst; |
| 1223 | struct skl_module_inst_id *pin_id; | ||
| 1224 | uuid_le *uuid_mod, *uuid_tplg; | ||
| 1225 | struct skl_module *skl_module; | ||
| 1197 | struct uuid_module *module; | 1226 | struct uuid_module *module; |
| 1198 | uuid_le *uuid_mod; | 1227 | int i, ret = -EIO; |
| 1199 | 1228 | ||
| 1200 | uuid_mod = (uuid_le *)mconfig->guid; | 1229 | uuid_mod = (uuid_le *)mconfig->guid; |
| 1201 | 1230 | ||
| @@ -1207,12 +1236,45 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) · 5 unmodified lines | |||
| 1207 | list_for_each_entry(module, &ctx->uuid_list, list) { | 1236 | list_for_each_entry(module, &ctx->uuid_list, list) { |
| 1208 | if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) { | 1237 | if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) { |
| 1209 | mconfig->id.module_id = module->id; | 1238 | mconfig->id.module_id = module->id; |
| 1210 | mconfig->is_loadable = module->is_loadable; | 1239 | if (mconfig->module) |
| 1211 | return 0; | 1240 | mconfig->module->loadable = module->is_loadable; |
| 1241 | ret = 0; | ||
| 1242 | break; | ||
| 1243 | } | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | if (ret) | ||
| 1247 | return ret; | ||
| 1248 | |||
| 1249 | uuid_mod = &module->uuid; | ||
| 1250 | ret = -EIO; | ||
| 1251 | for (i = 0; i < skl->nr_modules; i++) { | ||
| 1252 | skl_module = skl->modules[i]; | ||
| 1253 | uuid_tplg = &skl_module->uuid; | ||
| 1254 | if (!uuid_le_cmp(*uuid_mod, *uuid_tplg)) { | ||
| 1255 | mconfig->module = skl_module; | ||
| 1256 | ret = 0; | ||
| 1257 | break; | ||
| 1212 | } | 1258 | } |
| 1213 | } | 1259 | } |
| 1260 | if (skl->nr_modules && ret) | ||
| 1261 | return ret; | ||
| 1214 | 1262 | ||
| 1215 | return -EIO; | 1263 | list_for_each_entry(module, &ctx->uuid_list, list) { |
| 1264 | for (i = 0; i < MAX_IN_QUEUE; i++) { | ||
| 1265 | pin_id = &mconfig->m_in_pin[i].id; | ||
| 1266 | if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid)) | ||
| 1267 | pin_id->module_id = module->id; | ||
| 1268 | } | ||
| 1269 | |||
| 1270 | for (i = 0; i < MAX_OUT_QUEUE; i++) { | ||
| 1271 | pin_id = &mconfig->m_out_pin[i].id; | ||
| 1272 | if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid)) | ||
| 1273 | pin_id->module_id = module->id; | ||
| 1274 | } | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | return 0; | ||
| 1216 | } | 1278 | } |
| 1217 | 1279 | ||
| 1218 | static int skl_populate_modules(struct skl *skl) | 1280 | static int skl_populate_modules(struct skl *skl) |
| @@ -1284,7 +1346,7 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) · 65 unmodified lines | |||
| 1284 | 1346 | ||
| 1285 | return 0; | 1347 | return 0; |
| 1286 | } | 1348 | } |
| 1287 | static struct snd_soc_platform_driver skl_platform_drv = { | 1349 | static const struct snd_soc_platform_driver skl_platform_drv = { |
| 1288 | .probe = skl_platform_soc_probe, | 1350 | .probe = skl_platform_soc_probe, |
| 1289 | .ops = &skl_platform_ops, | 1351 | .ops = &skl_platform_ops, |
| 1290 | .pcm_new = skl_pcm_new, | 1352 | .pcm_new = skl_pcm_new, |
| @@ -47,7 +47,7 @@ void skl_dsp_init_core_state(struct sst_dsp *ctx) · 46 unmodified lines | |||
| 47 | skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; | 47 | skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; |
| 48 | skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1; | 48 | skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1; |
| 49 | 49 | ||
| 50 | for (i = SKL_DSP_CORE0_ID + 1; i < SKL_DSP_CORES_MAX; i++) { | 50 | for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) { |
| 51 | skl->cores.state[i] = SKL_DSP_RESET; | 51 | skl->cores.state[i] = SKL_DSP_RESET; |
| 52 | skl->cores.usage_count[i] = 0; | 52 | skl->cores.usage_count[i] = 0; |
| 53 | } | 53 | } |
| @@ -351,6 +351,8 @@ int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) · 297 unmodified lines | |||
| 351 | return -EINVAL; | 351 | return -EINVAL; |
| 352 | } | 352 | } |
| 353 | 353 | ||
| 354 | skl->cores.usage_count[core_id]++; | ||
| 355 | |||
| 354 | if (skl->cores.state[core_id] == SKL_DSP_RESET) { | 356 | if (skl->cores.state[core_id] == SKL_DSP_RESET) { |
| 355 | ret = ctx->fw_ops.set_state_D0(ctx, core_id); | 357 | ret = ctx->fw_ops.set_state_D0(ctx, core_id); |
| 356 | if (ret < 0) { | 358 | if (ret < 0) { |
| @@ -359,8 +361,6 @@ int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) · 2 unmodified lines | |||
| 359 | } | 361 | } |
| 360 | } | 362 | } |
| 361 | 363 | ||
| 362 | skl->cores.usage_count[core_id]++; | ||
| 363 | |||
| 364 | out: | 364 | out: |
| 365 | dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", | 365 | dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", |
| 366 | core_id, skl->cores.state[core_id], | 366 | core_id, skl->cores.state[core_id], |
| @@ -283,7 +283,7 @@ enum skl_ipc_module_msg { · 282 unmodified lines | |||
| 283 | IPC_MOD_SET_D0IX = 8 | 283 | IPC_MOD_SET_D0IX = 8 |
| 284 | }; | 284 | }; |
| 285 | 285 | ||
| 286 | static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, | 286 | void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, |
| 287 | size_t tx_size) | 287 | size_t tx_size) |
| 288 | { | 288 | { |
| 289 | if (tx_size) | 289 | if (tx_size) |
| @@ -347,7 +347,7 @@ out: · 57 unmodified lines | |||
| 347 | 347 | ||
| 348 | } | 348 | } |
| 349 | 349 | ||
| 350 | static int skl_ipc_process_notification(struct sst_generic_ipc *ipc, | 350 | int skl_ipc_process_notification(struct sst_generic_ipc *ipc, |
| 351 | struct skl_ipc_header header) | 351 | struct skl_ipc_header header) |
| 352 | { | 352 | { |
| 353 | struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); | 353 | struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); |
| @@ -406,7 +406,7 @@ static int skl_ipc_set_reply_error_code(u32 reply) · 52 unmodified lines | |||
| 406 | } | 406 | } |
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, | 409 | void skl_ipc_process_reply(struct sst_generic_ipc *ipc, |
| 410 | struct skl_ipc_header header) | 410 | struct skl_ipc_header header) |
| 411 | { | 411 | { |
| 412 | struct ipc_message *msg; | 412 | struct ipc_message *msg; |
| @@ -44,12 +44,10 @@ struct skl_ipc_header { · 43 unmodified lines | |||
| 44 | u32 extension; | 44 | u32 extension; |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | #define SKL_DSP_CORES_MAX 2 | ||
| 48 | |||
| 49 | struct skl_dsp_cores { | 47 | struct skl_dsp_cores { |
| 50 | unsigned int count; | 48 | unsigned int count; |
| 51 | enum skl_dsp_states state[SKL_DSP_CORES_MAX]; | 49 | enum skl_dsp_states *state; |
| 52 | int usage_count[SKL_DSP_CORES_MAX]; | 50 | int *usage_count; |
| 53 | }; | 51 | }; |
| 54 | 52 | ||
| 55 | /** | 53 | /** |
| @@ -214,4 +212,10 @@ void skl_ipc_free(struct sst_generic_ipc *ipc); · 158 unmodified lines | |||
| 214 | int skl_ipc_init(struct device *dev, struct skl_sst *skl); | 212 | int skl_ipc_init(struct device *dev, struct skl_sst *skl); |
| 215 | void skl_clear_module_cnt(struct sst_dsp *ctx); | 213 | void skl_clear_module_cnt(struct sst_dsp *ctx); |
| 216 | 214 | ||
| 215 | void skl_ipc_process_reply(struct sst_generic_ipc *ipc, | ||
| 216 | struct skl_ipc_header header); | ||
| 217 | int skl_ipc_process_notification(struct sst_generic_ipc *ipc, | ||
| 218 | struct skl_ipc_header header); | ||
| 219 | void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, | ||
| 220 | size_t tx_size); | ||
| 217 | #endif /* __SKL_IPC_H */ | 221 | #endif /* __SKL_IPC_H */ |
| @@ -368,7 +368,6 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, · 367 unmodified lines | |||
| 368 | { | 368 | { |
| 369 | struct skl_sst *skl; | 369 | struct skl_sst *skl; |
| 370 | struct sst_dsp *sst; | 370 | struct sst_dsp *sst; |
| 371 | int ret; | ||
| 372 | 371 | ||
| 373 | skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); | 372 | skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); |
| 374 | if (skl == NULL) | 373 | if (skl == NULL) |
| @@ -388,15 +387,12 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, · 13 unmodified lines | |||
| 388 | sst->dsp_ops = dsp_ops; | 387 | sst->dsp_ops = dsp_ops; |
| 389 | init_waitqueue_head(&skl->mod_load_wait); | 388 | init_waitqueue_head(&skl->mod_load_wait); |
| 390 | INIT_LIST_HEAD(&sst->module_list); | 389 | INIT_LIST_HEAD(&sst->module_list); |
| 391 | ret = skl_ipc_init(dev, skl); | ||
| 392 | if (ret) | ||
| 393 | return ret; | ||
| 394 | 390 | ||
| 395 | skl->is_first_boot = true; | 391 | skl->is_first_boot = true; |
| 396 | if (dsp) | 392 | if (dsp) |
| 397 | *dsp = skl; | 393 | *dsp = skl; |
| 398 | 394 | ||
| 399 | return ret; | 395 | return 0; |
| 400 | } | 396 | } |
| 401 | 397 | ||
| 402 | int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo, | 398 | int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo, |
| @@ -503,7 +503,7 @@ static void skl_clear_module_table(struct sst_dsp *ctx) · 502 unmodified lines | |||
| 503 | } | 503 | } |
| 504 | } | 504 | } |
| 505 | 505 | ||
| 506 | static struct skl_dsp_fw_ops skl_fw_ops = { | 506 | static const struct skl_dsp_fw_ops skl_fw_ops = { |
| 507 | .set_state_D0 = skl_set_dsp_D0, | 507 | .set_state_D0 = skl_set_dsp_D0, |
| 508 | .set_state_D3 = skl_set_dsp_D3, | 508 | .set_state_D3 = skl_set_dsp_D3, |
| 509 | .load_fw = skl_load_base_firmware, | 509 | .load_fw = skl_load_base_firmware, |
| @@ -512,7 +512,7 @@ static struct skl_dsp_fw_ops skl_fw_ops = { · 2 unmodified lines | |||
| 512 | .unload_mod = skl_unload_module, | 512 | .unload_mod = skl_unload_module, |
| 513 | }; | 513 | }; |
| 514 | 514 | ||
| 515 | static struct skl_dsp_fw_ops kbl_fw_ops = { | 515 | static const struct skl_dsp_fw_ops kbl_fw_ops = { |
| 516 | .set_state_D0 = skl_set_dsp_D0, | 516 | .set_state_D0 = skl_set_dsp_D0, |
| 517 | .set_state_D3 = skl_set_dsp_D3, | 517 | .set_state_D3 = skl_set_dsp_D3, |
| 518 | .load_fw = skl_load_base_firmware, | 518 | .load_fw = skl_load_base_firmware, |
| @@ -561,9 +561,13 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, · 42 unmodified lines | |||
| 561 | sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), | 561 | sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), |
| 562 | SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); | 562 | SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); |
| 563 | 563 | ||
| 564 | sst->fw_ops = skl_fw_ops; | 564 | ret = skl_ipc_init(dev, skl); |
| 565 | if (ret) { | ||
| 566 | skl_dsp_free(sst); | ||
| 567 | return ret; | ||
| 568 | } | ||
| 565 | 569 | ||
| 566 | skl->cores.count = 2; | 570 | sst->fw_ops = skl_fw_ops; |
| 567 | 571 | ||
| 568 | return 0; | 572 | return 0; |
| 569 | } | 573 | } |
| @@ -49,6 +49,9 @@ static const int mic_quatro_list[][SKL_CH_QUATRO] = { · 48 unmodified lines | |||
| 49 | {0, 1, 2, 3}, | 49 | {0, 1, 2, 3}, |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | #define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \ | ||
| 53 | ((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq)) | ||
| 54 | |||
| 52 | void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) | 55 | void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) |
| 53 | { | 56 | { |
| 54 | struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; | 57 | struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; |
| @@ -153,8 +156,10 @@ static bool skl_is_pipe_mcps_avail(struct skl *skl, · 98 unmodified lines | |||
| 153 | struct skl_module_cfg *mconfig) | 156 | struct skl_module_cfg *mconfig) |
| 154 | { | 157 | { |
| 155 | struct skl_sst *ctx = skl->skl_sst; | 158 | struct skl_sst *ctx = skl->skl_sst; |
| 159 | u8 res_idx = mconfig->res_idx; | ||
| 160 | struct skl_module_res *res = &mconfig->module->resources[res_idx]; | ||
| 156 | 161 | ||
| 157 | if (skl->resource.mcps + mconfig->mcps > skl->resource.max_mcps) { | 162 | if (skl->resource.mcps + res->cps > skl->resource.max_mcps) { |
| 158 | dev_err(ctx->dev, | 163 | dev_err(ctx->dev, |
| 159 | "%s: module_id %d instance %d\n", __func__, | 164 | "%s: module_id %d instance %d\n", __func__, |
| 160 | mconfig->id.module_id, mconfig->id.instance_id); | 165 | mconfig->id.module_id, mconfig->id.instance_id); |
| @@ -170,7 +175,10 @@ static bool skl_is_pipe_mcps_avail(struct skl *skl, · 9 unmodified lines | |||
| 170 | static void skl_tplg_alloc_pipe_mcps(struct skl *skl, | 175 | static void skl_tplg_alloc_pipe_mcps(struct skl *skl, |
| 171 | struct skl_module_cfg *mconfig) | 176 | struct skl_module_cfg *mconfig) |
| 172 | { | 177 | { |
| 173 | skl->resource.mcps += mconfig->mcps; | 178 | u8 res_idx = mconfig->res_idx; |
| 179 | struct skl_module_res *res = &mconfig->module->resources[res_idx]; | ||
| 180 | |||
| 181 | skl->resource.mcps += res->cps; | ||
| 174 | } | 182 | } |
| 175 | 183 | ||
| 176 | /* | 184 | /* |
| @@ -179,7 +187,11 @@ static void skl_tplg_alloc_pipe_mcps(struct skl *skl, · 2 unmodified lines | |||
| 179 | static void | 187 | static void |
| 180 | skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig) | 188 | skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig) |
| 181 | { | 189 | { |
| 182 | skl->resource.mcps -= mconfig->mcps; | 190 | u8 res_idx = mconfig->res_idx; |
| 191 | struct skl_module_res *res = &mconfig->module->resources[res_idx]; | ||
| 192 | |||
| 193 | res = &mconfig->module->resources[res_idx]; | ||
| 194 | skl->resource.mcps -= res->cps; | ||
| 183 | } | 195 | } |
| 184 | 196 | ||
| 185 | /* | 197 | /* |
| @@ -195,17 +207,21 @@ skl_tplg_free_pipe_mem(struct skl *skl, struct skl_module_cfg *mconfig) · 9 unmodified lines | |||
| 195 | static void skl_dump_mconfig(struct skl_sst *ctx, | 207 | static void skl_dump_mconfig(struct skl_sst *ctx, |
| 196 | struct skl_module_cfg *mcfg) | 208 | struct skl_module_cfg *mcfg) |
| 197 | { | 209 | { |
| 210 | struct skl_module_iface *iface = &mcfg->module->formats[0]; | ||
| 211 | |||
| 198 | dev_dbg(ctx->dev, "Dumping config\n"); | 212 | dev_dbg(ctx->dev, "Dumping config\n"); |
| 199 | dev_dbg(ctx->dev, "Input Format:\n"); | 213 | dev_dbg(ctx->dev, "Input Format:\n"); |
| 200 | dev_dbg(ctx->dev, "channels = %d\n", mcfg->in_fmt[0].channels); | 214 | dev_dbg(ctx->dev, "channels = %d\n", iface->inputs[0].fmt.channels); |
| 201 | dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->in_fmt[0].s_freq); | 215 | dev_dbg(ctx->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq); |
| 202 | dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->in_fmt[0].ch_cfg); | 216 | dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg); |
| 203 | dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->in_fmt[0].valid_bit_depth); | 217 | dev_dbg(ctx->dev, "valid bit depth = %d\n", |
| 218 | iface->inputs[0].fmt.valid_bit_depth); | ||
| 204 | dev_dbg(ctx->dev, "Output Format:\n"); | 219 | dev_dbg(ctx->dev, "Output Format:\n"); |
| 205 | dev_dbg(ctx->dev, "channels = %d\n", mcfg->out_fmt[0].channels); | 220 | dev_dbg(ctx->dev, "channels = %d\n", iface->outputs[0].fmt.channels); |
| 206 | dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->out_fmt[0].s_freq); | 221 | dev_dbg(ctx->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq); |
| 207 | dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->out_fmt[0].valid_bit_depth); | 222 | dev_dbg(ctx->dev, "valid bit depth = %d\n", |
| 208 | dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->out_fmt[0].ch_cfg); | 223 | iface->outputs[0].fmt.valid_bit_depth); |
| 224 | dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg); | ||
| 209 | } | 225 | } |
| 210 | 226 | ||
| 211 | static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) | 227 | static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) |
| @@ -273,8 +289,8 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg, · 61 unmodified lines | |||
| 273 | struct skl_module_fmt *in_fmt, *out_fmt; | 289 | struct skl_module_fmt *in_fmt, *out_fmt; |
| 274 | 290 | ||
| 275 | /* Fixups will be applied to pin 0 only */ | 291 | /* Fixups will be applied to pin 0 only */ |
| 276 | in_fmt = &m_cfg->in_fmt[0]; | 292 | in_fmt = &m_cfg->module->formats[0].inputs[0].fmt; |
| 277 | out_fmt = &m_cfg->out_fmt[0]; | 293 | out_fmt = &m_cfg->module->formats[0].outputs[0].fmt; |
| 278 | 294 | ||
| 279 | if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 295 | if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 280 | if (is_fe) { | 296 | if (is_fe) { |
| @@ -312,21 +328,23 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx, · 31 unmodified lines | |||
| 312 | { | 328 | { |
| 313 | int multiplier = 1; | 329 | int multiplier = 1; |
| 314 | struct skl_module_fmt *in_fmt, *out_fmt; | 330 | struct skl_module_fmt *in_fmt, *out_fmt; |
| 331 | struct skl_module_res *res; | ||
| 315 | 332 | ||
| 316 | /* Since fixups is applied to pin 0 only, ibs, obs needs | 333 | /* Since fixups is applied to pin 0 only, ibs, obs needs |
| 317 | * change for pin 0 only | 334 | * change for pin 0 only |
| 318 | */ | 335 | */ |
| 319 | in_fmt = &mcfg->in_fmt[0]; | 336 | res = &mcfg->module->resources[0]; |
| 320 | out_fmt = &mcfg->out_fmt[0]; | 337 | in_fmt = &mcfg->module->formats[0].inputs[0].fmt; |
| 338 | out_fmt = &mcfg->module->formats[0].outputs[0].fmt; | ||
| 321 | 339 | ||
| 322 | if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT) | 340 | if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT) |
| 323 | multiplier = 5; | 341 | multiplier = 5; |
| 324 | 342 | ||
| 325 | mcfg->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) * | 343 | res->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) * |
| 326 | in_fmt->channels * (in_fmt->bit_depth >> 3) * | 344 | in_fmt->channels * (in_fmt->bit_depth >> 3) * |
| 327 | multiplier; | 345 | multiplier; |
| 328 | 346 | ||
| 329 | mcfg->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) * | 347 | res->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) * |
| 330 | out_fmt->channels * (out_fmt->bit_depth >> 3) * | 348 | out_fmt->channels * (out_fmt->bit_depth >> 3) * |
| 331 | multiplier; | 349 | multiplier; |
| 332 | } | 350 | } |
| @@ -365,6 +383,8 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, · 32 unmodified lines | |||
| 365 | struct nhlt_specific_cfg *cfg; | 383 | struct nhlt_specific_cfg *cfg; |
| 366 | struct skl *skl = get_skl_ctx(ctx->dev); | 384 | struct skl *skl = get_skl_ctx(ctx->dev); |
| 367 | u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); | 385 | u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); |
| 386 | int fmt_idx = m_cfg->fmt_idx; | ||
| 387 | struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx]; | ||
| 368 | 388 | ||
| 369 | /* check if we already have blob */ | 389 | /* check if we already have blob */ |
| 370 | if (m_cfg->formats_config.caps_size > 0) | 390 | if (m_cfg->formats_config.caps_size > 0) |
| @@ -375,23 +395,23 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, · 4 unmodified lines | |||
| 375 | case SKL_DEVICE_DMIC: | 395 | case SKL_DEVICE_DMIC: |
| 376 | link_type = NHLT_LINK_DMIC; | 396 | link_type = NHLT_LINK_DMIC; |
| 377 | dir = SNDRV_PCM_STREAM_CAPTURE; | 397 | dir = SNDRV_PCM_STREAM_CAPTURE; |
| 378 | s_freq = m_cfg->in_fmt[0].s_freq; | 398 | s_freq = m_iface->inputs[0].fmt.s_freq; |
| 379 | s_fmt = m_cfg->in_fmt[0].bit_depth; | 399 | s_fmt = m_iface->inputs[0].fmt.bit_depth; |
| 380 | ch = m_cfg->in_fmt[0].channels; | 400 | ch = m_iface->inputs[0].fmt.channels; |
| 381 | break; | 401 | break; |
| 382 | 402 | ||
| 383 | case SKL_DEVICE_I2S: | 403 | case SKL_DEVICE_I2S: |
| 384 | link_type = NHLT_LINK_SSP; | 404 | link_type = NHLT_LINK_SSP; |
| 385 | if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) { | 405 | if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) { |
| 386 | dir = SNDRV_PCM_STREAM_PLAYBACK; | 406 | dir = SNDRV_PCM_STREAM_PLAYBACK; |
| 387 | s_freq = m_cfg->out_fmt[0].s_freq; | 407 | s_freq = m_iface->outputs[0].fmt.s_freq; |
| 388 | s_fmt = m_cfg->out_fmt[0].bit_depth; | 408 | s_fmt = m_iface->outputs[0].fmt.bit_depth; |
| 389 | ch = m_cfg->out_fmt[0].channels; | 409 | ch = m_iface->outputs[0].fmt.channels; |
| 390 | } else { | 410 | } else { |
| 391 | dir = SNDRV_PCM_STREAM_CAPTURE; | 411 | dir = SNDRV_PCM_STREAM_CAPTURE; |
| 392 | s_freq = m_cfg->in_fmt[0].s_freq; | 412 | s_freq = m_iface->inputs[0].fmt.s_freq; |
| 393 | s_fmt = m_cfg->in_fmt[0].bit_depth; | 413 | s_fmt = m_iface->inputs[0].fmt.bit_depth; |
| 394 | ch = m_cfg->in_fmt[0].channels; | 414 | ch = m_iface->inputs[0].fmt.channels; |
| 395 | } | 415 | } |
| 396 | break; | 416 | break; |
| 397 | 417 | ||
| @@ -549,6 +569,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) · 151 unmodified lines | |||
| 549 | struct snd_soc_dapm_widget *w; | 569 | struct snd_soc_dapm_widget *w; |
| 550 | struct skl_module_cfg *mconfig; | 570 | struct skl_module_cfg *mconfig; |
| 551 | struct skl_sst *ctx = skl->skl_sst; | 571 | struct skl_sst *ctx = skl->skl_sst; |
| 572 | u8 cfg_idx; | ||
| 552 | int ret = 0; | 573 | int ret = 0; |
| 553 | 574 | ||
| 554 | list_for_each_entry(w_module, &pipe->w_list, node) { | 575 | list_for_each_entry(w_module, &pipe->w_list, node) { |
| @@ -564,11 +585,15 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) · 9 unmodified lines | |||
| 564 | return -EIO; | 585 | return -EIO; |
| 565 | } | 586 | } |
| 566 | 587 | ||
| 588 | cfg_idx = mconfig->pipe->cur_config_idx; | ||
| 589 | mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; | ||
| 590 | mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; | ||
| 591 | |||
| 567 | /* check resource available */ | 592 | /* check resource available */ |
| 568 | if (!skl_is_pipe_mcps_avail(skl, mconfig)) | 593 | if (!skl_is_pipe_mcps_avail(skl, mconfig)) |
| 569 | return -ENOMEM; | 594 | return -ENOMEM; |
| 570 | 595 | ||
| 571 | if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) { | 596 | if (mconfig->module->loadable && ctx->dsp->fw_ops.load_mod) { |
| 572 | ret = ctx->dsp->fw_ops.load_mod(ctx->dsp, | 597 | ret = ctx->dsp->fw_ops.load_mod(ctx->dsp, |
| 573 | mconfig->id.module_id, mconfig->guid); | 598 | mconfig->id.module_id, mconfig->guid); |
| 574 | if (ret < 0) | 599 | if (ret < 0) |
| @@ -596,24 +621,35 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) · 21 unmodified lines | |||
| 596 | if (mconfig->id.pvt_id < 0) | 621 | if (mconfig->id.pvt_id < 0) |
| 597 | return ret; | 622 | return ret; |
| 598 | skl_tplg_set_module_init_data(w); | 623 | skl_tplg_set_module_init_data(w); |
| 624 | |||
| 625 | ret = skl_dsp_get_core(ctx->dsp, mconfig->core_id); | ||
| 626 | if (ret < 0) { | ||
| 627 | dev_err(ctx->dev, "Failed to wake up core %d ret=%d\n", | ||
| 628 | mconfig->core_id, ret); | ||
| 629 | return ret; | ||
| 630 | } | ||
| 631 | |||
| 599 | ret = skl_init_module(ctx, mconfig); | 632 | ret = skl_init_module(ctx, mconfig); |
| 600 | if (ret < 0) { | 633 | if (ret < 0) { |
| 601 | skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); | 634 | skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); |
| 602 | return ret; | 635 | goto err; |
| 603 | } | 636 | } |
| 604 | skl_tplg_alloc_pipe_mcps(skl, mconfig); | 637 | skl_tplg_alloc_pipe_mcps(skl, mconfig); |
| 605 | ret = skl_tplg_set_module_params(w, ctx); | 638 | ret = skl_tplg_set_module_params(w, ctx); |
| 606 | if (ret < 0) | 639 | if (ret < 0) |
| 607 | return ret; | 640 | goto err; |
| 608 | } | 641 | } |
| 609 | 642 | ||
| 610 | return 0; | 643 | return 0; |
| 644 | err: | ||
| 645 | skl_dsp_put_core(ctx->dsp, mconfig->core_id); | ||
| 646 | return ret; | ||
| 611 | } | 647 | } |
| 612 | 648 | ||
| 613 | static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, | 649 | static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, |
| 614 | struct skl_pipe *pipe) | 650 | struct skl_pipe *pipe) |
| 615 | { | 651 | { |
| 616 | int ret; | 652 | int ret = 0; |
| 617 | struct skl_pipe_module *w_module = NULL; | 653 | struct skl_pipe_module *w_module = NULL; |
| 618 | struct skl_module_cfg *mconfig = NULL; | 654 | struct skl_module_cfg *mconfig = NULL; |
| 619 | 655 | ||
| @@ -622,7 +658,7 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, · 2 unmodified lines | |||
| 622 | mconfig = w_module->w->priv; | 658 | mconfig = w_module->w->priv; |
| 623 | uuid_mod = (uuid_le *)mconfig->guid; | 659 | uuid_mod = (uuid_le *)mconfig->guid; |
| 624 | 660 | ||
| 625 | if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod && | 661 | if (mconfig->module->loadable && ctx->dsp->fw_ops.unload_mod && |
| 626 | mconfig->m_state > SKL_MODULE_UNINIT) { | 662 | mconfig->m_state > SKL_MODULE_UNINIT) { |
| 627 | ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp, | 663 | ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp, |
| 628 | mconfig->id.module_id); | 664 | mconfig->id.module_id); |
| @@ -630,10 +666,76 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, · 1 unmodified line | |||
| 630 | return -EIO; | 666 | return -EIO; |
| 631 | } | 667 | } |
| 632 | skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); | 668 | skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); |
| 669 | |||
| 670 | ret = skl_dsp_put_core(ctx->dsp, mconfig->core_id); | ||
| 671 | if (ret < 0) { | ||
| 672 | /* don't return; continue with other modules */ | ||
| 673 | dev_err(ctx->dev, "Failed to sleep core %d ret=%d\n", | ||
| 674 | mconfig->core_id, ret); | ||
| 675 | } | ||
| 633 | } | 676 | } |
| 634 | 677 | ||
| 635 | /* no modules to unload in this path, so return */ | 678 | /* no modules to unload in this path, so return */ |
| 636 | return 0; | 679 | return ret; |
| 680 | } | ||
| 681 | |||
| 682 | /* | ||
| 683 | * Here, we select pipe format based on the pipe type and pipe | ||
| 684 | * direction to determine the current config index for the pipeline. | ||
| 685 | * The config index is then used to select proper module resources. | ||
| 686 | * Intermediate pipes currently have a fixed format hence we select the | ||
| 687 | * 0th configuratation by default for such pipes. | ||
| 688 | */ | ||
| 689 | static int | ||
| 690 | skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig) | ||
| 691 | { | ||
| 692 | struct skl_sst *ctx = skl->skl_sst; | ||
| 693 | struct skl_pipe *pipe = mconfig->pipe; | ||
| 694 | struct skl_pipe_params *params = pipe->p_params; | ||
| 695 | struct skl_path_config *pconfig = &pipe->configs[0]; | ||
| 696 | struct skl_pipe_fmt *fmt = NULL; | ||
| 697 | bool in_fmt = false; | ||
| 698 | int i; | ||
| 699 | |||
| 700 | if (pipe->nr_cfgs == 0) { | ||
| 701 | pipe->cur_config_idx = 0; | ||
| 702 | return 0; | ||
| 703 | } | ||
| 704 | |||
| 705 | if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) { | ||
| 706 | dev_dbg(ctx->dev, "No conn_type detected, take 0th config\n"); | ||
| 707 | pipe->cur_config_idx = 0; | ||
| 708 | pipe->memory_pages = pconfig->mem_pages; | ||
| 709 | |||
| 710 | return 0; | ||
| 711 | } | ||
| 712 | |||
| 713 | if ((pipe->conn_type == SKL_PIPE_CONN_TYPE_FE && | ||
| 714 | pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) || | ||
| 715 | (pipe->conn_type == SKL_PIPE_CONN_TYPE_BE && | ||
| 716 | pipe->direction == SNDRV_PCM_STREAM_CAPTURE)) | ||
| 717 | in_fmt = true; | ||
| 718 | |||
| 719 | for (i = 0; i < pipe->nr_cfgs; i++) { | ||
| 720 | pconfig = &pipe->configs[i]; | ||
| 721 | if (in_fmt) | ||
| 722 | fmt = &pconfig->in_fmt; | ||
| 723 | else | ||
| 724 | fmt = &pconfig->out_fmt; | ||
| 725 | |||
| 726 | if (CHECK_HW_PARAMS(params->ch, params->s_freq, params->s_fmt, | ||
| 727 | fmt->channels, fmt->freq, fmt->bps)) { | ||
| 728 | pipe->cur_config_idx = i; | ||
| 729 | pipe->memory_pages = pconfig->mem_pages; | ||
| 730 | dev_dbg(ctx->dev, "Using pipe config: %d\n", i); | ||
| 731 | |||
| 732 | return 0; | ||
| 733 | } | ||
| 734 | } | ||
| 735 | |||
| 736 | dev_err(ctx->dev, "Invalid pipe config: %d %d %d for pipe: %d\n", | ||
| 737 | params->ch, params->s_freq, params->s_fmt, pipe->ppl_id); | ||
| 738 | return -EINVAL; | ||
| 637 | } | 739 | } |
| 638 | 740 | ||
| 639 | /* | 741 | /* |
| @@ -655,6 +757,10 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, · 15 unmodified lines | |||
| 655 | struct skl_sst *ctx = skl->skl_sst; | 757 | struct skl_sst *ctx = skl->skl_sst; |
| 656 | struct skl_module_deferred_bind *modules; | 758 | struct skl_module_deferred_bind *modules; |
| 657 | 759 | ||
| 760 | ret = skl_tplg_get_pipe_config(skl, mconfig); | ||
| 761 | if (ret < 0) | ||
| 762 | return ret; | ||
| 763 | |||
| 658 | /* check resource available */ | 764 | /* check resource available */ |
| 659 | if (!skl_is_pipe_mcps_avail(skl, mconfig)) | 765 | if (!skl_is_pipe_mcps_avail(skl, mconfig)) |
| 660 | return -EBUSY; | 766 | return -EBUSY; |
| @@ -758,12 +864,12 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, · 97 unmodified lines | |||
| 758 | * check all out/in pins are in bind state. | 864 | * check all out/in pins are in bind state. |
| 759 | * if so set the module param | 865 | * if so set the module param |
| 760 | */ | 866 | */ |
| 761 | for (i = 0; i < mcfg->max_out_queue; i++) { | 867 | for (i = 0; i < mcfg->module->max_output_pins; i++) { |
| 762 | if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE) | 868 | if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE) |
| 763 | return 0; | 869 | return 0; |
| 764 | } | 870 | } |
| 765 | 871 | ||
| 766 | for (i = 0; i < mcfg->max_in_queue; i++) { | 872 | for (i = 0; i < mcfg->module->max_input_pins; i++) { |
| 767 | if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE) | 873 | if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE) |
| 768 | return 0; | 874 | return 0; |
| 769 | } | 875 | } |
| @@ -814,7 +920,7 @@ static int skl_tplg_module_add_deferred_bind(struct skl *skl, · 44 unmodified lines | |||
| 814 | int i; | 920 | int i; |
| 815 | 921 | ||
| 816 | /* only supported for module with static pin connection */ | 922 | /* only supported for module with static pin connection */ |
| 817 | for (i = 0; i < dst->max_in_queue; i++) { | 923 | for (i = 0; i < dst->module->max_input_pins; i++) { |
| 818 | struct skl_module_pin *pin = &dst->m_in_pin[i]; | 924 | struct skl_module_pin *pin = &dst->m_in_pin[i]; |
| 819 | 925 | ||
| 820 | if (pin->is_dynamic) | 926 | if (pin->is_dynamic) |
| @@ -925,7 +1031,7 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, · 104 unmodified lines | |||
| 925 | } | 1031 | } |
| 926 | } | 1032 | } |
| 927 | 1033 | ||
| 928 | if (!sink) | 1034 | if (!sink && next_sink) |
| 929 | return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig); | 1035 | return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig); |
| 930 | 1036 | ||
| 931 | return 0; | 1037 | return 0; |
| @@ -1074,7 +1180,7 @@ static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, · 142 unmodified lines | |||
| 1074 | if (ret) | 1180 | if (ret) |
| 1075 | return ret; | 1181 | return ret; |
| 1076 | 1182 | ||
| 1077 | for (i = 0; i < sink_mconfig->max_in_queue; i++) { | 1183 | for (i = 0; i < sink_mconfig->module->max_input_pins; i++) { |
| 1078 | if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) { | 1184 | if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) { |
| 1079 | src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg; | 1185 | src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg; |
| 1080 | if (!src_mconfig) | 1186 | if (!src_mconfig) |
| @@ -1185,7 +1291,7 @@ static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, · 104 unmodified lines | |||
| 1185 | if (ret) | 1291 | if (ret) |
| 1186 | return ret; | 1292 | return ret; |
| 1187 | 1293 | ||
| 1188 | for (i = 0; i < src_mconfig->max_out_queue; i++) { | 1294 | for (i = 0; i < src_mconfig->module->max_output_pins; i++) { |
| 1189 | if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) { | 1295 | if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) { |
| 1190 | sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg; | 1296 | sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg; |
| 1191 | if (!sink_mconfig) | 1297 | if (!sink_mconfig) |
| @@ -1479,14 +1585,22 @@ int skl_tplg_update_pipe_params(struct device *dev, · 287 unmodified lines | |||
| 1479 | struct skl_module_cfg *mconfig, | 1585 | struct skl_module_cfg *mconfig, |
| 1480 | struct skl_pipe_params *params) | 1586 | struct skl_pipe_params *params) |
| 1481 | { | 1587 | { |
| 1588 | struct skl_module_res *res = &mconfig->module->resources[0]; | ||
| 1589 | struct skl *skl = get_skl_ctx(dev); | ||
| 1482 | struct skl_module_fmt *format = NULL; | 1590 | struct skl_module_fmt *format = NULL; |
| 1591 | u8 cfg_idx = mconfig->pipe->cur_config_idx; | ||
| 1483 | 1592 | ||
| 1484 | skl_tplg_fill_dma_id(mconfig, params); | 1593 | skl_tplg_fill_dma_id(mconfig, params); |
| 1594 | mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; | ||
| 1595 | mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; | ||
| 1596 | |||
| 1597 | if (skl->nr_modules) | ||
| 1598 | return 0; | ||
| 1485 | 1599 | ||
| 1486 | if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1600 | if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| 1487 | format = &mconfig->in_fmt[0]; | 1601 | format = &mconfig->module->formats[0].inputs[0].fmt; |
| 1488 | else | 1602 | else |
| 1489 | format = &mconfig->out_fmt[0]; | 1603 | format = &mconfig->module->formats[0].outputs[0].fmt; |
| 1490 | 1604 | ||
| 1491 | /* set the hw_params */ | 1605 | /* set the hw_params */ |
| 1492 | format->s_freq = params->s_freq; | 1606 | format->s_freq = params->s_freq; |
| @@ -1514,11 +1628,11 @@ int skl_tplg_update_pipe_params(struct device *dev, · 21 unmodified lines | |||
| 1514 | } | 1628 | } |
| 1515 | 1629 | ||
| 1516 | if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 1630 | if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 1517 | mconfig->ibs = (format->s_freq / 1000) * | 1631 | res->ibs = (format->s_freq / 1000) * |
| 1518 | (format->channels) * | 1632 | (format->channels) * |
| 1519 | (format->bit_depth >> 3); | 1633 | (format->bit_depth >> 3); |
| 1520 | } else { | 1634 | } else { |
| 1521 | mconfig->obs = (format->s_freq / 1000) * | 1635 | res->obs = (format->s_freq / 1000) * |
| 1522 | (format->channels) * | 1636 | (format->channels) * |
| 1523 | (format->bit_depth >> 3); | 1637 | (format->bit_depth >> 3); |
| 1524 | } | 1638 | } |
| @@ -1792,6 +1906,54 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { · 267 unmodified lines | |||
| 1792 | }, | 1906 | }, |
| 1793 | }; | 1907 | }; |
| 1794 | 1908 | ||
| 1909 | static int skl_tplg_fill_pipe_cfg(struct device *dev, | ||
| 1910 | struct skl_pipe *pipe, u32 tkn, | ||
| 1911 | u32 tkn_val, int conf_idx, int dir) | ||
| 1912 | { | ||
| 1913 | struct skl_pipe_fmt *fmt; | ||
| 1914 | struct skl_path_config *config; | ||
| 1915 | |||
| 1916 | switch (dir) { | ||
| 1917 | case SKL_DIR_IN: | ||
| 1918 | fmt = &pipe->configs[conf_idx].in_fmt; | ||
| 1919 | break; | ||
| 1920 | |||
| 1921 | case SKL_DIR_OUT: | ||
| 1922 | fmt = &pipe->configs[conf_idx].out_fmt; | ||
| 1923 | break; | ||
| 1924 | |||
| 1925 | default: | ||
| 1926 | dev_err(dev, "Invalid direction: %d\n", dir); | ||
| 1927 | return -EINVAL; | ||
| 1928 | } | ||
| 1929 | |||
| 1930 | config = &pipe->configs[conf_idx]; | ||
| 1931 | |||
| 1932 | switch (tkn) { | ||
| 1933 | case SKL_TKN_U32_CFG_FREQ: | ||
| 1934 | fmt->freq = tkn_val; | ||
| 1935 | break; | ||
| 1936 | |||
| 1937 | case SKL_TKN_U8_CFG_CHAN: | ||
| 1938 | fmt->channels = tkn_val; | ||
| 1939 | break; | ||
| 1940 | |||
| 1941 | case SKL_TKN_U8_CFG_BPS: | ||
| 1942 | fmt->bps = tkn_val; | ||
| 1943 | break; | ||
| 1944 | |||
| 1945 | case SKL_TKN_U32_PATH_MEM_PGS: | ||
| 1946 | config->mem_pages = tkn_val; | ||
| 1947 | break; | ||
| 1948 | |||
| 1949 | default: | ||
| 1950 | dev_err(dev, "Invalid token config: %d\n", tkn); | ||
| 1951 | return -EINVAL; | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | return 0; | ||
| 1955 | } | ||
| 1956 | |||
| 1795 | static int skl_tplg_fill_pipe_tkn(struct device *dev, | 1957 | static int skl_tplg_fill_pipe_tkn(struct device *dev, |
| 1796 | struct skl_pipe *pipe, u32 tkn, | 1958 | struct skl_pipe *pipe, u32 tkn, |
| 1797 | u32 tkn_val) | 1959 | u32 tkn_val) |
| @@ -1814,6 +1976,14 @@ static int skl_tplg_fill_pipe_tkn(struct device *dev, · 16 unmodified lines | |||
| 1814 | pipe->lp_mode = tkn_val; | 1976 | pipe->lp_mode = tkn_val; |
| 1815 | break; | 1977 | break; |
| 1816 | 1978 | ||
| 1979 | case SKL_TKN_U32_PIPE_DIRECTION: | ||
| 1980 | pipe->direction = tkn_val; | ||
| 1981 | break; | ||
| 1982 | |||
| 1983 | case SKL_TKN_U32_NUM_CONFIGS: | ||
| 1984 | pipe->nr_cfgs = tkn_val; | ||
| 1985 | break; | ||
| 1986 | |||
| 1817 | default: | 1987 | default: |
| 1818 | dev_err(dev, "Token not handled %d\n", tkn); | 1988 | dev_err(dev, "Token not handled %d\n", tkn); |
| 1819 | return -EINVAL; | 1989 | return -EINVAL; |
| @@ -1930,27 +2100,9 @@ static int skl_tplg_fill_pins_info(struct device *dev, · 110 unmodified lines | |||
| 1930 | * on the direction | 2100 | * on the direction |
| 1931 | */ | 2101 | */ |
| 1932 | static int skl_tplg_fill_fmt(struct device *dev, | 2102 | static int skl_tplg_fill_fmt(struct device *dev, |
| 1933 | struct skl_module_cfg *mconfig, u32 tkn, | 2103 | struct skl_module_fmt *dst_fmt, |
| 1934 | u32 value, u32 dir, u32 pin_count) | 2104 | u32 tkn, u32 value) |
| 1935 | { | 2105 | { |
| 1936 | struct skl_module_fmt *dst_fmt; | ||
| 1937 | |||
| 1938 | switch (dir) { | ||
| 1939 | case SKL_DIR_IN: | ||
| 1940 | dst_fmt = mconfig->in_fmt; | ||
| 1941 | dst_fmt += pin_count; | ||
| 1942 | break; | ||
| 1943 | |||
| 1944 | case SKL_DIR_OUT: | ||
| 1945 | dst_fmt = mconfig->out_fmt; | ||
| 1946 | dst_fmt += pin_count; | ||
| 1947 | break; | ||
| 1948 | |||
| 1949 | default: | ||
| 1950 | dev_err(dev, "Invalid direction value\n"); | ||
| 1951 | return -EINVAL; | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | switch (tkn) { | 2106 | switch (tkn) { |
| 1955 | case SKL_TKN_U32_FMT_CH: | 2107 | case SKL_TKN_U32_FMT_CH: |
| 1956 | dst_fmt->channels = value; | 2108 | dst_fmt->channels = value; |
| @@ -1992,6 +2144,32 @@ static int skl_tplg_fill_fmt(struct device *dev, · 35 unmodified lines | |||
| 1992 | return 0; | 2144 | return 0; |
| 1993 | } | 2145 | } |
| 1994 | 2146 | ||
| 2147 | static int skl_tplg_widget_fill_fmt(struct device *dev, | ||
| 2148 | struct skl_module_iface *fmt, | ||
| 2149 | u32 tkn, u32 val, u32 dir, int fmt_idx) | ||
| 2150 | { | ||
| 2151 | struct skl_module_fmt *dst_fmt; | ||
| 2152 | |||
| 2153 | if (!fmt) | ||
| 2154 | return -EINVAL; | ||
| 2155 | |||
| 2156 | switch (dir) { | ||
| 2157 | case SKL_DIR_IN: | ||
| 2158 | dst_fmt = &fmt->inputs[fmt_idx].fmt; | ||
| 2159 | break; | ||
| 2160 | |||
| 2161 | case SKL_DIR_OUT: | ||
| 2162 | dst_fmt = &fmt->outputs[fmt_idx].fmt; | ||
| 2163 | break; | ||
| 2164 | |||
| 2165 | default: | ||
| 2166 | dev_err(dev, "Invalid direction: %d\n", dir); | ||
| 2167 | return -EINVAL; | ||
| 2168 | } | ||
| 2169 | |||
| 2170 | return skl_tplg_fill_fmt(dev, dst_fmt, tkn, val); | ||
| 2171 | } | ||
| 2172 | |||
| 1995 | static int skl_tplg_get_uuid(struct device *dev, struct skl_module_cfg *mconfig, | 2173 | static int skl_tplg_get_uuid(struct device *dev, struct skl_module_cfg *mconfig, |
| 1996 | struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) | 2174 | struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) |
| 1997 | { | 2175 | { |
| @@ -2014,6 +2192,108 @@ static void skl_tplg_fill_pin_dynamic_val( · 16 unmodified lines | |||
| 2014 | mpin[i].is_dynamic = value; | 2192 | mpin[i].is_dynamic = value; |
| 2015 | } | 2193 | } |
| 2016 | 2194 | ||
| 2195 | /* | ||
| 2196 | * Resource table in the manifest has pin specific resources | ||
| 2197 | * like pin and pin buffer size | ||
| 2198 | */ | ||
| 2199 | static int skl_tplg_manifest_pin_res_tkn(struct device *dev, | ||
| 2200 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, | ||
| 2201 | struct skl_module_res *res, int pin_idx, int dir) | ||
| 2202 | { | ||
| 2203 | struct skl_module_pin_resources *m_pin; | ||
| 2204 | |||
| 2205 | switch (dir) { | ||
| 2206 | case SKL_DIR_IN: | ||
| 2207 | m_pin = &res->input[pin_idx]; | ||
| 2208 | break; | ||
| 2209 | |||
| 2210 | case SKL_DIR_OUT: | ||
| 2211 | m_pin = &res->output[pin_idx]; | ||
| 2212 | break; | ||
| 2213 | |||
| 2214 | default: | ||
| 2215 | dev_err(dev, "Invalid pin direction: %d\n", dir); | ||
| 2216 | return -EINVAL; | ||
| 2217 | } | ||
| 2218 | |||
| 2219 | switch (tkn_elem->token) { | ||
| 2220 | case SKL_TKN_MM_U32_RES_PIN_ID: | ||
| 2221 | m_pin->pin_index = tkn_elem->value; | ||
| 2222 | break; | ||
| 2223 | |||
| 2224 | case SKL_TKN_MM_U32_PIN_BUF: | ||
| 2225 | m_pin->buf_size = tkn_elem->value; | ||
| 2226 | break; | ||
| 2227 | |||
| 2228 | default: | ||
| 2229 | dev_err(dev, "Invalid token: %d\n", tkn_elem->token); | ||
| 2230 | return -EINVAL; | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | return 0; | ||
| 2234 | } | ||
| 2235 | |||
| 2236 | /* | ||
| 2237 | * Fill module specific resources from the manifest's resource | ||
| 2238 | * table like CPS, DMA size, mem_pages. | ||
| 2239 | */ | ||
| 2240 | static int skl_tplg_fill_res_tkn(struct device *dev, | ||
| 2241 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, | ||
| 2242 | struct skl_module_res *res, | ||
| 2243 | int pin_idx, int dir) | ||
| 2244 | { | ||
| 2245 | int ret, tkn_count = 0; | ||
| 2246 | |||
| 2247 | if (!res) | ||
| 2248 | return -EINVAL; | ||
| 2249 | |||
| 2250 | switch (tkn_elem->token) { | ||
| 2251 | case SKL_TKN_MM_U32_CPS: | ||
| 2252 | res->cps = tkn_elem->value; | ||
| 2253 | break; | ||
| 2254 | |||
| 2255 | case SKL_TKN_MM_U32_DMA_SIZE: | ||
| 2256 | res->dma_buffer_size = tkn_elem->value; | ||
| 2257 | break; | ||
| 2258 | |||
| 2259 | case SKL_TKN_MM_U32_CPC: | ||
| 2260 | res->cpc = tkn_elem->value; | ||
| 2261 | break; | ||
| 2262 | |||
| 2263 | case SKL_TKN_U32_MEM_PAGES: | ||
| 2264 | res->is_pages = tkn_elem->value; | ||
| 2265 | break; | ||
| 2266 | |||
| 2267 | case SKL_TKN_U32_OBS: | ||
| 2268 | res->obs = tkn_elem->value; | ||
| 2269 | break; | ||
| 2270 | |||
| 2271 | case SKL_TKN_U32_IBS: | ||
| 2272 | res->ibs = tkn_elem->value; | ||
| 2273 | break; | ||
| 2274 | |||
| 2275 | case SKL_TKN_U32_MAX_MCPS: | ||
| 2276 | res->cps = tkn_elem->value; | ||
| 2277 | break; | ||
| 2278 | |||
| 2279 | case SKL_TKN_MM_U32_RES_PIN_ID: | ||
| 2280 | case SKL_TKN_MM_U32_PIN_BUF: | ||
| 2281 | ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res, | ||
| 2282 | pin_idx, dir); | ||
| 2283 | if (ret < 0) | ||
| 2284 | return ret; | ||
| 2285 | break; | ||
| 2286 | |||
| 2287 | default: | ||
| 2288 | dev_err(dev, "Not a res type token: %d", tkn_elem->token); | ||
| 2289 | return -EINVAL; | ||
| 2290 | |||
| 2291 | } | ||
| 2292 | tkn_count++; | ||
| 2293 | |||
| 2294 | return tkn_count; | ||
| 2295 | } | ||
| 2296 | |||
| 2017 | /* | 2297 | /* |
| 2018 | * Parse tokens to fill up the module private data | 2298 | * Parse tokens to fill up the module private data |
| 2019 | */ | 2299 | */ |
| @@ -2024,49 +2304,54 @@ static int skl_tplg_get_token(struct device *dev, · 4 unmodified lines | |||
| 2024 | int tkn_count = 0; | 2304 | int tkn_count = 0; |
| 2025 | int ret; | 2305 | int ret; |
| 2026 | static int is_pipe_exists; | 2306 | static int is_pipe_exists; |
| 2027 | static int pin_index, dir; | 2307 | static int pin_index, dir, conf_idx; |
| 2308 | struct skl_module_iface *iface = NULL; | ||
| 2309 | struct skl_module_res *res = NULL; | ||
| 2310 | int res_idx = mconfig->res_idx; | ||
| 2311 | int fmt_idx = mconfig->fmt_idx; | ||
| 2312 | |||
| 2313 | /* | ||
| 2314 | * If the manifest structure contains no modules, fill all | ||
| 2315 | * the module data to 0th index. | ||
| 2316 | * res_idx and fmt_idx are default set to 0. | ||
| 2317 | */ | ||
| 2318 | if (skl->nr_modules == 0) { | ||
| 2319 | res = &mconfig->module->resources[res_idx]; | ||
| 2320 | iface = &mconfig->module->formats[fmt_idx]; | ||
| 2321 | } | ||
| 2028 | 2322 | ||
| 2029 | if (tkn_elem->token > SKL_TKN_MAX) | 2323 | if (tkn_elem->token > SKL_TKN_MAX) |
| 2030 | return -EINVAL; | 2324 | return -EINVAL; |
| 2031 | 2325 | ||
| 2032 | switch (tkn_elem->token) { | 2326 | switch (tkn_elem->token) { |
| 2033 | case SKL_TKN_U8_IN_QUEUE_COUNT: | 2327 | case SKL_TKN_U8_IN_QUEUE_COUNT: |
| 2034 | mconfig->max_in_queue = tkn_elem->value; | 2328 | mconfig->module->max_input_pins = tkn_elem->value; |
| 2035 | mconfig->m_in_pin = devm_kzalloc(dev, mconfig->max_in_queue * | ||
| 2036 | sizeof(*mconfig->m_in_pin), | ||
| 2037 | GFP_KERNEL); | ||
| 2038 | if (!mconfig->m_in_pin) | ||
| 2039 | return -ENOMEM; | ||
| 2040 | |||
| 2041 | break; | 2329 | break; |
| 2042 | 2330 | ||
| 2043 | case SKL_TKN_U8_OUT_QUEUE_COUNT: | 2331 | case SKL_TKN_U8_OUT_QUEUE_COUNT: |
| 2044 | mconfig->max_out_queue = tkn_elem->value; | 2332 | mconfig->module->max_output_pins = tkn_elem->value; |
| 2045 | mconfig->m_out_pin = devm_kzalloc(dev, mconfig->max_out_queue * | ||
| 2046 | sizeof(*mconfig->m_out_pin), | ||
| 2047 | GFP_KERNEL); | ||
| 2048 | |||
| 2049 | if (!mconfig->m_out_pin) | ||
| 2050 | return -ENOMEM; | ||
| 2051 | |||
| 2052 | break; | 2333 | break; |
| 2053 | 2334 | ||
| 2054 | case SKL_TKN_U8_DYN_IN_PIN: | 2335 | case SKL_TKN_U8_DYN_IN_PIN: |
| 2336 | if (!mconfig->m_in_pin) | ||
| 2337 | mconfig->m_in_pin = devm_kzalloc(dev, MAX_IN_QUEUE * | ||
| 2338 | sizeof(*mconfig->m_in_pin), GFP_KERNEL); | ||
| 2055 | if (!mconfig->m_in_pin) | 2339 | if (!mconfig->m_in_pin) |
| 2056 | return -ENOMEM; | 2340 | return -ENOMEM; |
| 2057 | 2341 | ||
| 2058 | skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, | 2342 | skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, MAX_IN_QUEUE, |
| 2059 | mconfig->max_in_queue, tkn_elem->value); | 2343 | tkn_elem->value); |
| 2060 | |||
| 2061 | break; | 2344 | break; |
| 2062 | 2345 | ||
| 2063 | case SKL_TKN_U8_DYN_OUT_PIN: | 2346 | case SKL_TKN_U8_DYN_OUT_PIN: |
| 2347 | if (!mconfig->m_out_pin) | ||
| 2348 | mconfig->m_out_pin = devm_kzalloc(dev, MAX_IN_QUEUE * | ||
| 2349 | sizeof(*mconfig->m_in_pin), GFP_KERNEL); | ||
| 2064 | if (!mconfig->m_out_pin) | 2350 | if (!mconfig->m_out_pin) |
| 2065 | return -ENOMEM; | 2351 | return -ENOMEM; |
| 2066 | 2352 | ||
| 2067 | skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, | 2353 | skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, MAX_OUT_QUEUE, |
| 2068 | mconfig->max_out_queue, tkn_elem->value); | 2354 | tkn_elem->value); |
| 2069 | |||
| 2070 | break; | 2355 | break; |
| 2071 | 2356 | ||
| 2072 | case SKL_TKN_U8_TIME_SLOT: | 2357 | case SKL_TKN_U8_TIME_SLOT: |
| @@ -2094,19 +2379,13 @@ static int skl_tplg_get_token(struct device *dev, · 21 unmodified lines | |||
| 2094 | break; | 2379 | break; |
| 2095 | 2380 | ||
| 2096 | case SKL_TKN_U32_MEM_PAGES: | 2381 | case SKL_TKN_U32_MEM_PAGES: |
| 2097 | mconfig->mem_pages = tkn_elem->value; | ||
| 2098 | break; | ||
| 2099 | |||
| 2100 | case SKL_TKN_U32_MAX_MCPS: | 2382 | case SKL_TKN_U32_MAX_MCPS: |
| 2101 | mconfig->mcps = tkn_elem->value; | ||
| 2102 | break; | ||
| 2103 | |||
| 2104 | case SKL_TKN_U32_OBS: | 2383 | case SKL_TKN_U32_OBS: |
| 2105 | mconfig->obs = tkn_elem->value; | ||
| 2106 | break; | ||
| 2107 | |||
| 2108 | case SKL_TKN_U32_IBS: | 2384 | case SKL_TKN_U32_IBS: |
| 2109 | mconfig->ibs = tkn_elem->value; | 2385 | ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, dir, pin_index); |
| 2386 | if (ret < 0) | ||
| 2387 | return ret; | ||
| 2388 | |||
| 2110 | break; | 2389 | break; |
| 2111 | 2390 | ||
| 2112 | case SKL_TKN_U32_VBUS_ID: | 2391 | case SKL_TKN_U32_VBUS_ID: |
| @@ -2139,10 +2418,16 @@ static int skl_tplg_get_token(struct device *dev, · 26 unmodified lines | |||
| 2139 | 2418 | ||
| 2140 | break; | 2419 | break; |
| 2141 | 2420 | ||
| 2421 | case SKL_TKN_U32_PIPE_CONFIG_ID: | ||
| 2422 | conf_idx = tkn_elem->value; | ||
| 2423 | break; | ||
| 2424 | |||
| 2142 | case SKL_TKN_U32_PIPE_CONN_TYPE: | 2425 | case SKL_TKN_U32_PIPE_CONN_TYPE: |
| 2143 | case SKL_TKN_U32_PIPE_PRIORITY: | 2426 | case SKL_TKN_U32_PIPE_PRIORITY: |
| 2144 | case SKL_TKN_U32_PIPE_MEM_PGS: | 2427 | case SKL_TKN_U32_PIPE_MEM_PGS: |
| 2145 | case SKL_TKN_U32_PMODE: | 2428 | case SKL_TKN_U32_PMODE: |
| 2429 | case SKL_TKN_U32_PIPE_DIRECTION: | ||
| 2430 | case SKL_TKN_U32_NUM_CONFIGS: | ||
| 2146 | if (is_pipe_exists) { | 2431 | if (is_pipe_exists) { |
| 2147 | ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe, | 2432 | ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe, |
| 2148 | tkn_elem->token, tkn_elem->value); | 2433 | tkn_elem->token, tkn_elem->value); |
| @@ -2152,6 +2437,27 @@ static int skl_tplg_get_token(struct device *dev, · 3 unmodified lines | |||
| 2152 | 2437 | ||
| 2153 | break; | 2438 | break; |
| 2154 | 2439 | ||
| 2440 | case SKL_TKN_U32_PATH_MEM_PGS: | ||
| 2441 | case SKL_TKN_U32_CFG_FREQ: | ||
| 2442 | case SKL_TKN_U8_CFG_CHAN: | ||
| 2443 | case SKL_TKN_U8_CFG_BPS: | ||
| 2444 | if (mconfig->pipe->nr_cfgs) { | ||
| 2445 | ret = skl_tplg_fill_pipe_cfg(dev, mconfig->pipe, | ||
| 2446 | tkn_elem->token, tkn_elem->value, | ||
| 2447 | conf_idx, dir); | ||
| 2448 | if (ret < 0) | ||
| 2449 | return ret; | ||
| 2450 | } | ||
| 2451 | break; | ||
| 2452 | |||
| 2453 | case SKL_TKN_CFG_MOD_RES_ID: | ||
| 2454 | mconfig->mod_cfg[conf_idx].res_idx = tkn_elem->value; | ||
| 2455 | break; | ||
| 2456 | |||
| 2457 | case SKL_TKN_CFG_MOD_FMT_ID: | ||
| 2458 | mconfig->mod_cfg[conf_idx].fmt_idx = tkn_elem->value; | ||
| 2459 | break; | ||
| 2460 | |||
| 2155 | /* | 2461 | /* |
| 2156 | * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both | 2462 | * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both |
| 2157 | * direction and the pin count. The first four bits represent | 2463 | * direction and the pin count. The first four bits represent |
| @@ -2172,7 +2478,7 @@ static int skl_tplg_get_token(struct device *dev, · 14 unmodified lines | |||
| 2172 | case SKL_TKN_U32_FMT_INTERLEAVE: | 2478 | case SKL_TKN_U32_FMT_INTERLEAVE: |
| 2173 | case SKL_TKN_U32_FMT_SAMPLE_TYPE: | 2479 | case SKL_TKN_U32_FMT_SAMPLE_TYPE: |
| 2174 | case SKL_TKN_U32_FMT_CH_MAP: | 2480 | case SKL_TKN_U32_FMT_CH_MAP: |
| 2175 | ret = skl_tplg_fill_fmt(dev, mconfig, tkn_elem->token, | 2481 | ret = skl_tplg_widget_fill_fmt(dev, iface, tkn_elem->token, |
| 2176 | tkn_elem->value, dir, pin_index); | 2482 | tkn_elem->value, dir, pin_index); |
| 2177 | 2483 | ||
| 2178 | if (ret < 0) | 2484 | if (ret < 0) |
| @@ -2397,11 +2703,11 @@ static void skl_clear_pin_config(struct snd_soc_platform *platform, · 218 unmodified lines | |||
| 2397 | strlen(platform->component.name))) { | 2703 | strlen(platform->component.name))) { |
| 2398 | mconfig = w->priv; | 2704 | mconfig = w->priv; |
| 2399 | pipe = mconfig->pipe; | 2705 | pipe = mconfig->pipe; |
| 2400 | for (i = 0; i < mconfig->max_in_queue; i++) { | 2706 | for (i = 0; i < mconfig->module->max_input_pins; i++) { |
| 2401 | mconfig->m_in_pin[i].in_use = false; | 2707 | mconfig->m_in_pin[i].in_use = false; |
| 2402 | mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND; | 2708 | mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND; |
| 2403 | } | 2709 | } |
| 2404 | for (i = 0; i < mconfig->max_out_queue; i++) { | 2710 | for (i = 0; i < mconfig->module->max_output_pins; i++) { |
| 2405 | mconfig->m_out_pin[i].in_use = false; | 2711 | mconfig->m_out_pin[i].in_use = false; |
| 2406 | mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND; | 2712 | mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND; |
| 2407 | } | 2713 | } |
| @@ -2460,6 +2766,13 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, · 52 unmodified lines | |||
| 2460 | if (!mconfig) | 2766 | if (!mconfig) |
| 2461 | return -ENOMEM; | 2767 | return -ENOMEM; |
| 2462 | 2768 | ||
| 2769 | if (skl->nr_modules == 0) { | ||
| 2770 | mconfig->module = devm_kzalloc(bus->dev, | ||
| 2771 | sizeof(*mconfig->module), GFP_KERNEL); | ||
| 2772 | if (!mconfig->module) | ||
| 2773 | return -ENOMEM; | ||
| 2774 | } | ||
| 2775 | |||
| 2463 | w->priv = mconfig; | 2776 | w->priv = mconfig; |
| 2464 | 2777 | ||
| 2465 | /* | 2778 | /* |
| @@ -2602,13 +2915,13 @@ static int skl_tplg_fill_str_mfest_tkn(struct device *dev, · 136 unmodified lines | |||
| 2602 | str_elem->string, | 2915 | str_elem->string, |
| 2603 | ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name)); | 2916 | ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name)); |
| 2604 | ref_count++; | 2917 | ref_count++; |
| 2605 | tkn_count++; | ||
| 2606 | break; | 2918 | break; |
| 2607 | 2919 | ||
| 2608 | default: | 2920 | default: |
| 2609 | dev_err(dev, "Not a string token %d\n", str_elem->token); | 2921 | dev_err(dev, "Not a string token %d\n", str_elem->token); |
| 2610 | break; | 2922 | break; |
| 2611 | } | 2923 | } |
| 2924 | tkn_count++; | ||
| 2612 | 2925 | ||
| 2613 | return tkn_count; | 2926 | return tkn_count; |
| 2614 | } | 2927 | } |
| @@ -2634,26 +2947,236 @@ static int skl_tplg_get_str_tkn(struct device *dev, · 19 unmodified lines | |||
| 2634 | return tkn_count; | 2947 | return tkn_count; |
| 2635 | } | 2948 | } |
| 2636 | 2949 | ||
| 2950 | static int skl_tplg_manifest_fill_fmt(struct device *dev, | ||
| 2951 | struct skl_module_iface *fmt, | ||
| 2952 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, | ||
| 2953 | u32 dir, int fmt_idx) | ||
| 2954 | { | ||
| 2955 | struct skl_module_pin_fmt *dst_fmt; | ||
| 2956 | struct skl_module_fmt *mod_fmt; | ||
| 2957 | int ret; | ||
| 2958 | |||
| 2959 | if (!fmt) | ||
| 2960 | return -EINVAL; | ||
| 2961 | |||
| 2962 | switch (dir) { | ||
| 2963 | case SKL_DIR_IN: | ||
| 2964 | dst_fmt = &fmt->inputs[fmt_idx]; | ||
| 2965 | break; | ||
| 2966 | |||
| 2967 | case SKL_DIR_OUT: | ||
| 2968 | dst_fmt = &fmt->outputs[fmt_idx]; | ||
| 2969 | break; | ||
| 2970 | |||
| 2971 | default: | ||
| 2972 | dev_err(dev, "Invalid direction: %d\n", dir); | ||
| 2973 | return -EINVAL; | ||
| 2974 | } | ||
| 2975 | |||
| 2976 | mod_fmt = &dst_fmt->fmt; | ||
| 2977 | |||
| 2978 | switch (tkn_elem->token) { | ||
| 2979 | case SKL_TKN_MM_U32_INTF_PIN_ID: | ||
| 2980 | dst_fmt->id = tkn_elem->value; | ||
| 2981 | break; | ||
| 2982 | |||
| 2983 | default: | ||
| 2984 | ret = skl_tplg_fill_fmt(dev, mod_fmt, tkn_elem->token, | ||
| 2985 | tkn_elem->value); | ||
| 2986 | if (ret < 0) | ||
| 2987 | return ret; | ||
| 2988 | break; | ||
| 2989 | } | ||
| 2990 | |||
| 2991 | return 0; | ||
| 2992 | } | ||
| 2993 | |||
| 2994 | static int skl_tplg_fill_mod_info(struct device *dev, | ||
| 2995 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, | ||
| 2996 | struct skl_module *mod) | ||
| 2997 | { | ||
| 2998 | |||
| 2999 | if (!mod) | ||
| 3000 | return -EINVAL; | ||
| 3001 | |||
| 3002 | switch (tkn_elem->token) { | ||
| 3003 | case SKL_TKN_U8_IN_PIN_TYPE: | ||
| 3004 | mod->input_pin_type = tkn_elem->value; | ||
| 3005 | break; | ||
| 3006 | |||
| 3007 | case SKL_TKN_U8_OUT_PIN_TYPE: | ||
| 3008 | mod->output_pin_type = tkn_elem->value; | ||
| 3009 | break; | ||
| 3010 | |||
| 3011 | case SKL_TKN_U8_IN_QUEUE_COUNT: | ||
| 3012 | mod->max_input_pins = tkn_elem->value; | ||
| 3013 | break; | ||
| 3014 | |||
| 3015 | case SKL_TKN_U8_OUT_QUEUE_COUNT: | ||
| 3016 | mod->max_output_pins = tkn_elem->value; | ||
| 3017 | break; | ||
| 3018 | |||
| 3019 | case SKL_TKN_MM_U8_NUM_RES: | ||
| 3020 | mod->nr_resources = tkn_elem->value; | ||
| 3021 | break; | ||
| 3022 | |||
| 3023 | case SKL_TKN_MM_U8_NUM_INTF: | ||
| 3024 | mod->nr_interfaces = tkn_elem->value; | ||
| 3025 | break; | ||
| 3026 | |||
| 3027 | default: | ||
| 3028 | dev_err(dev, "Invalid mod info token %d", tkn_elem->token); | ||
| 3029 | return -EINVAL; | ||
| 3030 | } | ||
| 3031 | |||
| 3032 | return 0; | ||
| 3033 | } | ||
| 3034 | |||
| 3035 | |||
| 2637 | static int skl_tplg_get_int_tkn(struct device *dev, | 3036 | static int skl_tplg_get_int_tkn(struct device *dev, |
| 2638 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, | 3037 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, |
| 2639 | struct skl *skl) | 3038 | struct skl *skl) |
| 2640 | { | 3039 | { |
| 2641 | int tkn_count = 0; | 3040 | int tkn_count = 0, ret; |
| 3041 | static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; | ||
| 3042 | struct skl_module_res *res = NULL; | ||
| 3043 | struct skl_module_iface *fmt = NULL; | ||
| 3044 | struct skl_module *mod = NULL; | ||
| 3045 | int i; | ||
| 3046 | |||
| 3047 | if (skl->modules) { | ||
| 3048 | mod = skl->modules[mod_idx]; | ||
| 3049 | res = &mod->resources[res_val_idx]; | ||
| 3050 | fmt = &mod->formats[intf_val_idx]; | ||
| 3051 | } | ||
| 2642 | 3052 | ||
| 2643 | switch (tkn_elem->token) { | 3053 | switch (tkn_elem->token) { |
| 2644 | case SKL_TKN_U32_LIB_COUNT: | 3054 | case SKL_TKN_U32_LIB_COUNT: |
| 2645 | skl->skl_sst->lib_count = tkn_elem->value; | 3055 | skl->skl_sst->lib_count = tkn_elem->value; |
| 2646 | tkn_count++; | 3056 | break; |
| 3057 | |||
| 3058 | case SKL_TKN_U8_NUM_MOD: | ||
| 3059 | skl->nr_modules = tkn_elem->value; | ||
| 3060 | skl->modules = devm_kcalloc(dev, skl->nr_modules, | ||
| 3061 | sizeof(*skl->modules), GFP_KERNEL); | ||
| 3062 | if (!skl->modules) | ||
| 3063 | return -ENOMEM; | ||
| 3064 | |||
| 3065 | for (i = 0; i < skl->nr_modules; i++) { | ||
| 3066 | skl->modules[i] = devm_kzalloc(dev, | ||
| 3067 | sizeof(struct skl_module), GFP_KERNEL); | ||
| 3068 | if (!skl->modules[i]) | ||
| 3069 | return -ENOMEM; | ||
| 3070 | } | ||
| 3071 | break; | ||
| 3072 | |||
| 3073 | case SKL_TKN_MM_U8_MOD_IDX: | ||
| 3074 | mod_idx = tkn_elem->value; | ||
| 3075 | break; | ||
| 3076 | |||
| 3077 | case SKL_TKN_U8_IN_PIN_TYPE: | ||
| 3078 | case SKL_TKN_U8_OUT_PIN_TYPE: | ||
| 3079 | case SKL_TKN_U8_IN_QUEUE_COUNT: | ||
| 3080 | case SKL_TKN_U8_OUT_QUEUE_COUNT: | ||
| 3081 | case SKL_TKN_MM_U8_NUM_RES: | ||
| 3082 | case SKL_TKN_MM_U8_NUM_INTF: | ||
| 3083 | ret = skl_tplg_fill_mod_info(dev, tkn_elem, mod); | ||
| 3084 | if (ret < 0) | ||
| 3085 | return ret; | ||
| 3086 | break; | ||
| 3087 | |||
| 3088 | case SKL_TKN_U32_DIR_PIN_COUNT: | ||
| 3089 | dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; | ||
| 3090 | pin_idx = (tkn_elem->value & SKL_PIN_COUNT_MASK) >> 4; | ||
| 3091 | break; | ||
| 3092 | |||
| 3093 | case SKL_TKN_MM_U32_RES_ID: | ||
| 3094 | if (!res) | ||
| 3095 | return -EINVAL; | ||
| 3096 | |||
| 3097 | res->id = tkn_elem->value; | ||
| 3098 | res_val_idx = tkn_elem->value; | ||
| 3099 | break; | ||
| 3100 | |||
| 3101 | case SKL_TKN_MM_U32_FMT_ID: | ||
| 3102 | if (!fmt) | ||
| 3103 | return -EINVAL; | ||
| 3104 | |||
| 3105 | fmt->fmt_idx = tkn_elem->value; | ||
| 3106 | intf_val_idx = tkn_elem->value; | ||
| 3107 | break; | ||
| 3108 | |||
| 3109 | case SKL_TKN_MM_U32_CPS: | ||
| 3110 | case SKL_TKN_MM_U32_DMA_SIZE: | ||
| 3111 | case SKL_TKN_MM_U32_CPC: | ||
| 3112 | case SKL_TKN_U32_MEM_PAGES: | ||
| 3113 | case SKL_TKN_U32_OBS: | ||
| 3114 | case SKL_TKN_U32_IBS: | ||
| 3115 | case SKL_TKN_MM_U32_RES_PIN_ID: | ||
| 3116 | case SKL_TKN_MM_U32_PIN_BUF: | ||
| 3117 | ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_idx, dir); | ||
| 3118 | if (ret < 0) | ||
| 3119 | return ret; | ||
| 3120 | |||
| 3121 | break; | ||
| 3122 | |||
| 3123 | case SKL_TKN_MM_U32_NUM_IN_FMT: | ||
| 3124 | if (!fmt) | ||
| 3125 | return -EINVAL; | ||
| 3126 | |||
| 3127 | res->nr_input_pins = tkn_elem->value; | ||
| 3128 | break; | ||
| 3129 | |||
| 3130 | case SKL_TKN_MM_U32_NUM_OUT_FMT: | ||
| 3131 | if (!fmt) | ||
| 3132 | return -EINVAL; | ||
| 3133 | |||
| 3134 | res->nr_output_pins = tkn_elem->value; | ||
| 3135 | break; | ||
| 3136 | |||
| 3137 | case SKL_TKN_U32_FMT_CH: | ||
| 3138 | case SKL_TKN_U32_FMT_FREQ: | ||
| 3139 | case SKL_TKN_U32_FMT_BIT_DEPTH: | ||
| 3140 | case SKL_TKN_U32_FMT_SAMPLE_SIZE: | ||
| 3141 | case SKL_TKN_U32_FMT_CH_CONFIG: | ||
| 3142 | case SKL_TKN_U32_FMT_INTERLEAVE: | ||
| 3143 | case SKL_TKN_U32_FMT_SAMPLE_TYPE: | ||
| 3144 | case SKL_TKN_U32_FMT_CH_MAP: | ||
| 3145 | case SKL_TKN_MM_U32_INTF_PIN_ID: | ||
| 3146 | ret = skl_tplg_manifest_fill_fmt(dev, fmt, tkn_elem, | ||
| 3147 | dir, pin_idx); | ||
| 3148 | if (ret < 0) | ||
| 3149 | return ret; | ||
| 2647 | break; | 3150 | break; |
| 2648 | 3151 | ||
| 2649 | default: | 3152 | default: |
| 2650 | dev_err(dev, "Not a manifest token %d\n", tkn_elem->token); | 3153 | dev_err(dev, "Not a manifest token %d\n", tkn_elem->token); |
| 2651 | return -EINVAL; | 3154 | return -EINVAL; |
| 2652 | } | 3155 | } |
| 3156 | tkn_count++; | ||
| 2653 | 3157 | ||
| 2654 | return tkn_count; | 3158 | return tkn_count; |
| 2655 | } | 3159 | } |
| 2656 | 3160 | ||
| 3161 | static int skl_tplg_get_manifest_uuid(struct device *dev, | ||
| 3162 | struct skl *skl, | ||
| 3163 | struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) | ||
| 3164 | { | ||
| 3165 | static int ref_count; | ||
| 3166 | struct skl_module *mod; | ||
| 3167 | |||
| 3168 | if (uuid_tkn->token == SKL_TKN_UUID) { | ||
| 3169 | mod = skl->modules[ref_count]; | ||
| 3170 | memcpy(&mod->uuid, &uuid_tkn->uuid, sizeof(uuid_tkn->uuid)); | ||
| 3171 | ref_count++; | ||
| 3172 | } else { | ||
| 3173 | dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token); | ||
| 3174 | return -EINVAL; | ||
| 3175 | } | ||
| 3176 | |||
| 3177 | return 0; | ||
| 3178 | } | ||
| 3179 | |||
| 2657 | /* | 3180 | /* |
| 2658 | * Fill the manifest structure by parsing the tokens based on the | 3181 | * Fill the manifest structure by parsing the tokens based on the |
| 2659 | * type. | 3182 | * type. |
| @@ -2686,7 +3209,11 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, · 26 unmodified lines | |||
| 2686 | continue; | 3209 | continue; |
| 2687 | 3210 | ||
| 2688 | case SND_SOC_TPLG_TUPLE_TYPE_UUID: | 3211 | case SND_SOC_TPLG_TUPLE_TYPE_UUID: |
| 2689 | dev_warn(dev, "no uuid tokens for skl tplf manifest\n"); | 3212 | ret = skl_tplg_get_manifest_uuid(dev, skl, array->uuid); |
| 3213 | if (ret < 0) | ||
| 3214 | return ret; | ||
| 3215 | |||
| 3216 | tuple_size += sizeof(*array->uuid); | ||
| 2690 | continue; | 3217 | continue; |
| 2691 | 3218 | ||
| 2692 | default: | 3219 | default: |
| @@ -2703,14 +3230,12 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, · 10 unmodified lines | |||
| 2703 | 3230 | ||
| 2704 | tkn_count = tkn_count + ret; | 3231 | tkn_count = tkn_count + ret; |
| 2705 | tkn_elem++; | 3232 | tkn_elem++; |
| 2706 | tuple_size += tkn_count * | ||
| 2707 | sizeof(struct snd_soc_tplg_vendor_value_elem); | ||
| 2708 | break; | ||
| 2709 | } | 3233 | } |
| 3234 | tuple_size += (tkn_count * sizeof(*tkn_elem)); | ||
| 2710 | tkn_count = 0; | 3235 | tkn_count = 0; |
| 2711 | } | 3236 | } |
| 2712 | 3237 | ||
| 2713 | return 0; | 3238 | return off; |
| 2714 | } | 3239 | } |
| 2715 | 3240 | ||
| 2716 | /* | 3241 | /* |
| @@ -2733,11 +3258,10 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, · 16 unmodified lines | |||
| 2733 | num_blocks = ret; | 3258 | num_blocks = ret; |
| 2734 | 3259 | ||
| 2735 | off += array->size; | 3260 | off += array->size; |
| 2736 | array = (struct snd_soc_tplg_vendor_array *) | ||
| 2737 | (manifest->priv.data + off); | ||
| 2738 | |||
| 2739 | /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ | 3261 | /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ |
| 2740 | while (num_blocks > 0) { | 3262 | while (num_blocks > 0) { |
| 3263 | array = (struct snd_soc_tplg_vendor_array *) | ||
| 3264 | (manifest->priv.data + off); | ||
| 2741 | ret = skl_tplg_get_desc_blocks(dev, array); | 3265 | ret = skl_tplg_get_desc_blocks(dev, array); |
| 2742 | 3266 | ||
| 2743 | if (ret < 0) | 3267 | if (ret < 0) |
| @@ -2771,6 +3295,7 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, · 27 unmodified lines | |||
| 2771 | } else { | 3295 | } else { |
| 2772 | return -EINVAL; | 3296 | return -EINVAL; |
| 2773 | } | 3297 | } |
| 3298 | off += ret; | ||
| 2774 | } | 3299 | } |
| 2775 | 3300 | ||
| 2776 | return 0; | 3301 | return 0; |
| @@ -44,6 +44,13 @@ · 43 unmodified lines | |||
| 44 | #define SKL_DEFAULT_MIC_SEL_GAIN 0x3FF | 44 | #define SKL_DEFAULT_MIC_SEL_GAIN 0x3FF |
| 45 | #define SKL_MIC_SEL_SWITCH 0x3 | 45 | #define SKL_MIC_SEL_SWITCH 0x3 |
| 46 | 46 | ||
| 47 | #define SKL_OUTPUT_PIN 0 | ||
| 48 | #define SKL_INPUT_PIN 1 | ||
| 49 | #define SKL_MAX_PATH_CONFIGS 8 | ||
| 50 | #define SKL_MAX_MODULES_IN_PIPE 8 | ||
| 51 | #define SKL_MAX_MODULE_FORMATS 32 | ||
| 52 | #define SKL_MAX_MODULE_RESOURCES 32 | ||
| 53 | |||
| 47 | enum skl_channel_index { | 54 | enum skl_channel_index { |
| 48 | SKL_CHANNEL_LEFT = 0, | 55 | SKL_CHANNEL_LEFT = 0, |
| 49 | SKL_CHANNEL_RIGHT = 1, | 56 | SKL_CHANNEL_RIGHT = 1, |
| @@ -131,6 +138,11 @@ struct skl_cpr_cfg { · 81 unmodified lines | |||
| 131 | struct skl_cpr_gtw_cfg gtw_cfg; | 138 | struct skl_cpr_gtw_cfg gtw_cfg; |
| 132 | } __packed; | 139 | } __packed; |
| 133 | 140 | ||
| 141 | struct skl_cpr_pin_fmt { | ||
| 142 | u32 sink_id; | ||
| 143 | struct skl_audio_data_format src_fmt; | ||
| 144 | struct skl_audio_data_format dst_fmt; | ||
| 145 | } __packed; | ||
| 134 | 146 | ||
| 135 | struct skl_src_module_cfg { | 147 | struct skl_src_module_cfg { |
| 136 | struct skl_base_cfg base_cfg; | 148 | struct skl_base_cfg base_cfg; |
| @@ -214,6 +226,7 @@ struct skl_kpb_params { · 77 unmodified lines | |||
| 214 | }; | 226 | }; |
| 215 | 227 | ||
| 216 | struct skl_module_inst_id { | 228 | struct skl_module_inst_id { |
| 229 | uuid_le mod_uuid; | ||
| 217 | int module_id; | 230 | int module_id; |
| 218 | u32 instance_id; | 231 | u32 instance_id; |
| 219 | int pvt_id; | 232 | int pvt_id; |
| @@ -266,6 +279,23 @@ struct skl_pipe_params { · 46 unmodified lines | |||
| 266 | unsigned int link_bps; | 279 | unsigned int link_bps; |
| 267 | }; | 280 | }; |
| 268 | 281 | ||
| 282 | struct skl_pipe_fmt { | ||
| 283 | u32 freq; | ||
| 284 | u8 channels; | ||
| 285 | u8 bps; | ||
| 286 | }; | ||
| 287 | |||
| 288 | struct skl_pipe_mcfg { | ||
| 289 | u8 res_idx; | ||
| 290 | u8 fmt_idx; | ||
| 291 | }; | ||
| 292 | |||
| 293 | struct skl_path_config { | ||
| 294 | u8 mem_pages; | ||
| 295 | struct skl_pipe_fmt in_fmt; | ||
| 296 | struct skl_pipe_fmt out_fmt; | ||
| 297 | }; | ||
| 298 | |||
| 269 | struct skl_pipe { | 299 | struct skl_pipe { |
| 270 | u8 ppl_id; | 300 | u8 ppl_id; |
| 271 | u8 pipe_priority; | 301 | u8 pipe_priority; |
| @@ -274,6 +304,10 @@ struct skl_pipe { · 2 unmodified lines | |||
| 274 | u8 lp_mode; | 304 | u8 lp_mode; |
| 275 | struct skl_pipe_params *p_params; | 305 | struct skl_pipe_params *p_params; |
| 276 | enum skl_pipe_state state; | 306 | enum skl_pipe_state state; |
| 307 | u8 direction; | ||
| 308 | u8 cur_config_idx; | ||
| 309 | u8 nr_cfgs; | ||
| 310 | struct skl_path_config configs[SKL_MAX_PATH_CONFIGS]; | ||
| 277 | struct list_head w_list; | 311 | struct list_head w_list; |
| 278 | bool passthru; | 312 | bool passthru; |
| 279 | }; | 313 | }; |
| @@ -292,9 +326,57 @@ enum d0i3_capability { · 12 unmodified lines | |||
| 292 | SKL_D0I3_NON_STREAMING = 2, | 326 | SKL_D0I3_NON_STREAMING = 2, |
| 293 | }; | 327 | }; |
| 294 | 328 | ||
| 329 | struct skl_module_pin_fmt { | ||
| 330 | u8 id; | ||
| 331 | struct skl_module_fmt fmt; | ||
| 332 | }; | ||
| 333 | |||
| 334 | struct skl_module_iface { | ||
| 335 | u8 fmt_idx; | ||
| 336 | u8 nr_in_fmt; | ||
| 337 | u8 nr_out_fmt; | ||
| 338 | struct skl_module_pin_fmt inputs[MAX_IN_QUEUE]; | ||
| 339 | struct skl_module_pin_fmt outputs[MAX_OUT_QUEUE]; | ||
| 340 | }; | ||
| 341 | |||
| 342 | struct skl_module_pin_resources { | ||
| 343 | u8 pin_index; | ||
| 344 | u32 buf_size; | ||
| 345 | }; | ||
| 346 | |||
| 347 | struct skl_module_res { | ||
| 348 | u8 id; | ||
| 349 | u32 is_pages; | ||
| 350 | u32 cps; | ||
| 351 | u32 ibs; | ||
| 352 | u32 obs; | ||
| 353 | u32 dma_buffer_size; | ||
| 354 | u32 cpc; | ||
| 355 | u8 nr_input_pins; | ||
| 356 | u8 nr_output_pins; | ||
| 357 | struct skl_module_pin_resources input[MAX_IN_QUEUE]; | ||
| 358 | struct skl_module_pin_resources output[MAX_OUT_QUEUE]; | ||
| 359 | }; | ||
| 360 | |||
| 361 | struct skl_module { | ||
| 362 | uuid_le uuid; | ||
| 363 | u8 loadable; | ||
| 364 | u8 input_pin_type; | ||
| 365 | u8 output_pin_type; | ||
| 366 | u8 max_input_pins; | ||
| 367 | u8 max_output_pins; | ||
| 368 | u8 nr_resources; | ||
| 369 | u8 nr_interfaces; | ||
| 370 | struct skl_module_res resources[SKL_MAX_MODULE_RESOURCES]; | ||
| 371 | struct skl_module_iface formats[SKL_MAX_MODULE_FORMATS]; | ||
| 372 | }; | ||
| 373 | |||
| 295 | struct skl_module_cfg { | 374 | struct skl_module_cfg { |
| 296 | u8 guid[16]; | 375 | u8 guid[16]; |
| 297 | struct skl_module_inst_id id; | 376 | struct skl_module_inst_id id; |
| 377 | struct skl_module *module; | ||
| 378 | int res_idx; | ||
| 379 | int fmt_idx; | ||
| 298 | u8 domain; | 380 | u8 domain; |
| 299 | bool homogenous_inputs; | 381 | bool homogenous_inputs; |
| 300 | bool homogenous_outputs; | 382 | bool homogenous_outputs; |
| @@ -329,6 +411,7 @@ struct skl_module_cfg { · 28 unmodified lines | |||
| 329 | enum skl_module_state m_state; | 411 | enum skl_module_state m_state; |
| 330 | struct skl_pipe *pipe; | 412 | struct skl_pipe *pipe; |
| 331 | struct skl_specific_cfg formats_config; | 413 | struct skl_specific_cfg formats_config; |
| 414 | struct skl_pipe_mcfg mod_cfg[SKL_MAX_MODULES_IN_PIPE]; | ||
| 332 | }; | 415 | }; |
| 333 | 416 | ||
| 334 | struct skl_algo_data { | 417 | struct skl_algo_data { |
| @@ -415,7 +415,7 @@ static int skl_free(struct hdac_ext_bus *ebus) · 414 unmodified lines | |||
| 415 | snd_hdac_ext_stop_streams(ebus); | 415 | snd_hdac_ext_stop_streams(ebus); |
| 416 | 416 | ||
| 417 | if (bus->irq >= 0) | 417 | if (bus->irq >= 0) |
| 418 | free_irq(bus->irq, (void *)bus); | 418 | free_irq(bus->irq, (void *)ebus); |
| 419 | snd_hdac_bus_free_stream_pages(bus); | 419 | snd_hdac_bus_free_stream_pages(bus); |
| 420 | snd_hdac_stream_free_all(ebus); | 420 | snd_hdac_stream_free_all(ebus); |
| 421 | snd_hdac_link_free_all(ebus); | 421 | snd_hdac_link_free_all(ebus); |
| @@ -528,7 +528,7 @@ static int probe_codec(struct hdac_ext_bus *ebus, int addr) · 106 unmodified lines | |||
| 528 | } | 528 | } |
| 529 | 529 | ||
| 530 | /* Codec initialization */ | 530 | /* Codec initialization */ |
| 531 | static int skl_codec_create(struct hdac_ext_bus *ebus) | 531 | static void skl_codec_create(struct hdac_ext_bus *ebus) |
| 532 | { | 532 | { |
| 533 | struct hdac_bus *bus = ebus_to_hbus(ebus); | 533 | struct hdac_bus *bus = ebus_to_hbus(ebus); |
| 534 | int c, max_slots; | 534 | int c, max_slots; |
| @@ -559,8 +559,6 @@ static int skl_codec_create(struct hdac_ext_bus *ebus) · 24 unmodified lines | |||
| 559 | } | 559 | } |
| 560 | } | 560 | } |
| 561 | } | 561 | } |
| 562 | |||
| 563 | return 0; | ||
| 564 | } | 562 | } |
| 565 | 563 | ||
| 566 | static const struct hdac_bus_ops bus_core_ops = { | 564 | static const struct hdac_bus_ops bus_core_ops = { |
| @@ -612,9 +610,7 @@ static void skl_probe_work(struct work_struct *work) · 45 unmodified lines | |||
| 612 | dev_info(bus->dev, "no hda codecs found!\n"); | 610 | dev_info(bus->dev, "no hda codecs found!\n"); |
| 613 | 611 | ||
| 614 | /* create codec instances */ | 612 | /* create codec instances */ |
| 615 | err = skl_codec_create(ebus); | 613 | skl_codec_create(ebus); |
| 616 | if (err < 0) | ||
| 617 | goto out_err; | ||
| 618 | 614 | ||
| 619 | if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { | 615 | if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { |
| 620 | err = snd_hdac_display_power(bus, false); | 616 | err = snd_hdac_display_power(bus, false); |
| @@ -702,6 +698,8 @@ static int skl_first_init(struct hdac_ext_bus *ebus) · 81 unmodified lines | |||
| 702 | return -ENXIO; | 698 | return -ENXIO; |
| 703 | } | 699 | } |
| 704 | 700 | ||
| 701 | skl_init_chip(bus, true); | ||
| 702 | |||
| 705 | snd_hdac_bus_parse_capabilities(bus); | 703 | snd_hdac_bus_parse_capabilities(bus); |
| 706 | 704 | ||
| 707 | if (skl_acquire_irq(ebus, 0) < 0) | 705 | if (skl_acquire_irq(ebus, 0) < 0) |
| @@ -982,6 +980,11 @@ static struct sst_acpi_mach sst_kbl_devdata[] = { · 274 unmodified lines | |||
| 982 | .quirk_data = &kbl_poppy_codecs, | 980 | .quirk_data = &kbl_poppy_codecs, |
| 983 | .pdata = &skl_dmic_data | 981 | .pdata = &skl_dmic_data |
| 984 | }, | 982 | }, |
| 983 | { | ||
| 984 | .id = "10EC5663", | ||
| 985 | .drv_name = "kbl_rt5663", | ||
| 986 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
| 987 | }, | ||
| 985 | 988 | ||
| 986 | {} | 989 | {} |
| 987 | }; | 990 | }; |
| @@ -995,6 +998,14 @@ static struct sst_acpi_mach sst_glk_devdata[] = { · 7 unmodified lines | |||
| 995 | {} | 998 | {} |
| 996 | }; | 999 | }; |
| 997 | 1000 | ||
| 1001 | static const struct sst_acpi_mach sst_cnl_devdata[] = { | ||
| 1002 | { | ||
| 1003 | .id = "INT34C2", | ||
| 1004 | .drv_name = "cnl_rt274", | ||
| 1005 | .fw_filename = "intel/dsp_fw_cnl.bin", | ||
| 1006 | }, | ||
| 1007 | }; | ||
| 1008 | |||
| 998 | /* PCI IDs */ | 1009 | /* PCI IDs */ |
| 999 | static const struct pci_device_id skl_ids[] = { | 1010 | static const struct pci_device_id skl_ids[] = { |
| 1000 | /* Sunrise Point-LP */ | 1011 | /* Sunrise Point-LP */ |
| @@ -1009,6 +1020,9 @@ static const struct pci_device_id skl_ids[] = { · 8 unmodified lines | |||
| 1009 | /* GLK */ | 1020 | /* GLK */ |
| 1010 | { PCI_DEVICE(0x8086, 0x3198), | 1021 | { PCI_DEVICE(0x8086, 0x3198), |
| 1011 | .driver_data = (unsigned long)&sst_glk_devdata}, | 1022 | .driver_data = (unsigned long)&sst_glk_devdata}, |
| 1023 | /* CNL */ | ||
| 1024 | { PCI_DEVICE(0x8086, 0x9dc8), | ||
| 1025 | .driver_data = (unsigned long)&sst_cnl_devdata}, | ||
| 1012 | { 0, } | 1026 | { 0, } |
| 1013 | }; | 1027 | }; |
| 1014 | MODULE_DEVICE_TABLE(pci, skl_ids); | 1028 | MODULE_DEVICE_TABLE(pci, skl_ids); |
| @@ -71,6 +71,8 @@ struct skl { · 70 unmodified lines | |||
| 71 | struct work_struct probe_work; | 71 | struct work_struct probe_work; |
| 72 | 72 | ||
| 73 | struct skl_debug *debugfs; | 73 | struct skl_debug *debugfs; |
| 74 | u8 nr_modules; | ||
| 75 | struct skl_module **modules; | ||
| 74 | }; | 76 | }; |
| 75 | 77 | ||
| 76 | #define skl_to_ebus(s) (&(s)->ebus) | 78 | #define skl_to_ebus(s) (&(s)->ebus) |
| @@ -90,6 +92,7 @@ struct skl_machine_pdata { · 13 unmodified lines | |||
| 90 | 92 | ||
| 91 | struct skl_dsp_ops { | 93 | struct skl_dsp_ops { |
| 92 | int id; | 94 | int id; |
| 95 | unsigned int num_cores; | ||
| 93 | struct skl_dsp_loader_ops (*loader_ops)(void); | 96 | struct skl_dsp_loader_ops (*loader_ops)(void); |
| 94 | int (*init)(struct device *dev, void __iomem *mmio_base, | 97 | int (*init)(struct device *dev, void __iomem *mmio_base, |
| 95 | int irq, const char *fw_name, | 98 | int irq, const char *fw_name, |