@@ -551,6 +551,178 @@ static const struct sdw_master_ops amd_sdw_ops = {
551551 .read_ping_status = amd_sdw_read_ping_status ,
552552};
553553
554+ static int amd_sdw_hw_params (struct snd_pcm_substream * substream ,
555+ struct snd_pcm_hw_params * params ,
556+ struct snd_soc_dai * dai )
557+ {
558+ struct amd_sdw_manager * amd_manager = snd_soc_dai_get_drvdata (dai );
559+ struct sdw_amd_dai_runtime * dai_runtime ;
560+ struct sdw_stream_config sconfig ;
561+ struct sdw_port_config * pconfig ;
562+ int ch , dir ;
563+ int ret ;
564+
565+ dai_runtime = amd_manager -> dai_runtime_array [dai -> id ];
566+ if (!dai_runtime )
567+ return - EIO ;
568+
569+ ch = params_channels (params );
570+ if (substream -> stream == SNDRV_PCM_STREAM_CAPTURE )
571+ dir = SDW_DATA_DIR_RX ;
572+ else
573+ dir = SDW_DATA_DIR_TX ;
574+ dev_dbg (amd_manager -> dev , "dir:%d dai->id:0x%x\n" , dir , dai -> id );
575+
576+ sconfig .direction = dir ;
577+ sconfig .ch_count = ch ;
578+ sconfig .frame_rate = params_rate (params );
579+ sconfig .type = dai_runtime -> stream_type ;
580+
581+ sconfig .bps = snd_pcm_format_width (params_format (params ));
582+
583+ /* Port configuration */
584+ pconfig = kzalloc (sizeof (* pconfig ), GFP_KERNEL );
585+ if (!pconfig ) {
586+ ret = - ENOMEM ;
587+ goto error ;
588+ }
589+
590+ pconfig -> num = dai -> id ;
591+ pconfig -> ch_mask = (1 << ch ) - 1 ;
592+ ret = sdw_stream_add_master (& amd_manager -> bus , & sconfig ,
593+ pconfig , 1 , dai_runtime -> stream );
594+ if (ret )
595+ dev_err (amd_manager -> dev , "add manager to stream failed:%d\n" , ret );
596+
597+ kfree (pconfig );
598+ error :
599+ return ret ;
600+ }
601+
602+ static int amd_sdw_hw_free (struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
603+ {
604+ struct amd_sdw_manager * amd_manager = snd_soc_dai_get_drvdata (dai );
605+ struct sdw_amd_dai_runtime * dai_runtime ;
606+ int ret ;
607+
608+ dai_runtime = amd_manager -> dai_runtime_array [dai -> id ];
609+ if (!dai_runtime )
610+ return - EIO ;
611+
612+ ret = sdw_stream_remove_master (& amd_manager -> bus , dai_runtime -> stream );
613+ if (ret < 0 )
614+ dev_err (dai -> dev , "remove manager from stream %s failed: %d\n" ,
615+ dai_runtime -> stream -> name , ret );
616+ return ret ;
617+ }
618+
619+ static int amd_set_sdw_stream (struct snd_soc_dai * dai , void * stream , int direction )
620+ {
621+ struct amd_sdw_manager * amd_manager = snd_soc_dai_get_drvdata (dai );
622+ struct sdw_amd_dai_runtime * dai_runtime ;
623+
624+ dai_runtime = amd_manager -> dai_runtime_array [dai -> id ];
625+ if (stream ) {
626+ /* first paranoia check */
627+ if (dai_runtime ) {
628+ dev_err (dai -> dev , "dai_runtime already allocated for dai %s\n" , dai -> name );
629+ return - EINVAL ;
630+ }
631+
632+ /* allocate and set dai_runtime info */
633+ dai_runtime = kzalloc (sizeof (* dai_runtime ), GFP_KERNEL );
634+ if (!dai_runtime )
635+ return - ENOMEM ;
636+
637+ dai_runtime -> stream_type = SDW_STREAM_PCM ;
638+ dai_runtime -> bus = & amd_manager -> bus ;
639+ dai_runtime -> stream = stream ;
640+ amd_manager -> dai_runtime_array [dai -> id ] = dai_runtime ;
641+ } else {
642+ /* second paranoia check */
643+ if (!dai_runtime ) {
644+ dev_err (dai -> dev , "dai_runtime not allocated for dai %s\n" , dai -> name );
645+ return - EINVAL ;
646+ }
647+
648+ /* for NULL stream we release allocated dai_runtime */
649+ kfree (dai_runtime );
650+ amd_manager -> dai_runtime_array [dai -> id ] = NULL ;
651+ }
652+ return 0 ;
653+ }
654+
655+ static int amd_pcm_set_sdw_stream (struct snd_soc_dai * dai , void * stream , int direction )
656+ {
657+ return amd_set_sdw_stream (dai , stream , direction );
658+ }
659+
660+ static void * amd_get_sdw_stream (struct snd_soc_dai * dai , int direction )
661+ {
662+ struct amd_sdw_manager * amd_manager = snd_soc_dai_get_drvdata (dai );
663+ struct sdw_amd_dai_runtime * dai_runtime ;
664+
665+ dai_runtime = amd_manager -> dai_runtime_array [dai -> id ];
666+ if (!dai_runtime )
667+ return ERR_PTR (- EINVAL );
668+
669+ return dai_runtime -> stream ;
670+ }
671+
672+ static const struct snd_soc_dai_ops amd_sdw_dai_ops = {
673+ .hw_params = amd_sdw_hw_params ,
674+ .hw_free = amd_sdw_hw_free ,
675+ .set_stream = amd_pcm_set_sdw_stream ,
676+ .get_stream = amd_get_sdw_stream ,
677+ };
678+
679+ static const struct snd_soc_component_driver amd_sdw_dai_component = {
680+ .name = "soundwire" ,
681+ };
682+
683+ static int amd_sdw_register_dais (struct amd_sdw_manager * amd_manager )
684+ {
685+ struct sdw_amd_dai_runtime * * dai_runtime_array ;
686+ struct snd_soc_dai_driver * dais ;
687+ struct snd_soc_pcm_stream * stream ;
688+ struct device * dev ;
689+ int i , num_dais ;
690+
691+ dev = amd_manager -> dev ;
692+ num_dais = amd_manager -> num_dout_ports + amd_manager -> num_din_ports ;
693+ dais = devm_kcalloc (dev , num_dais , sizeof (* dais ), GFP_KERNEL );
694+ if (!dais )
695+ return - ENOMEM ;
696+
697+ dai_runtime_array = devm_kcalloc (dev , num_dais ,
698+ sizeof (struct sdw_amd_dai_runtime * ),
699+ GFP_KERNEL );
700+ if (!dai_runtime_array )
701+ return - ENOMEM ;
702+ amd_manager -> dai_runtime_array = dai_runtime_array ;
703+ for (i = 0 ; i < num_dais ; i ++ ) {
704+ dais [i ].name = devm_kasprintf (dev , GFP_KERNEL , "SDW%d Pin%d" , amd_manager -> instance ,
705+ i );
706+ if (!dais [i ].name )
707+ return - ENOMEM ;
708+ if (i < amd_manager -> num_dout_ports )
709+ stream = & dais [i ].playback ;
710+ else
711+ stream = & dais [i ].capture ;
712+
713+ stream -> channels_min = 2 ;
714+ stream -> channels_max = 2 ;
715+ stream -> rates = SNDRV_PCM_RATE_48000 ;
716+ stream -> formats = SNDRV_PCM_FMTBIT_S16_LE ;
717+
718+ dais [i ].ops = & amd_sdw_dai_ops ;
719+ dais [i ].id = i ;
720+ }
721+
722+ return devm_snd_soc_register_component (dev , & amd_sdw_dai_component ,
723+ dais , num_dais );
724+ }
725+
554726static void amd_sdw_probe_work (struct work_struct * work )
555727{
556728 struct amd_sdw_manager * amd_manager = container_of (work , struct amd_sdw_manager ,
@@ -636,6 +808,12 @@ static int amd_sdw_manager_probe(struct platform_device *pdev)
636808 dev_err (dev , "Failed to register SoundWire manager(%d)\n" , ret );
637809 return ret ;
638810 }
811+ ret = amd_sdw_register_dais (amd_manager );
812+ if (ret ) {
813+ dev_err (dev , "CPU DAI registration failed\n" );
814+ sdw_bus_master_delete (& amd_manager -> bus );
815+ return ret ;
816+ }
639817 dev_set_drvdata (dev , amd_manager );
640818 INIT_WORK (& amd_manager -> probe_work , amd_sdw_probe_work );
641819 /*
0 commit comments