root/sound/soc/meson/axg-card.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. axg_card_reallocate_links
  2. axg_card_parse_dai
  3. axg_card_set_link_name
  4. axg_card_clean_references
  5. axg_card_add_aux_devices
  6. axg_card_tdm_be_hw_params
  7. axg_card_tdm_dai_init
  8. axg_card_tdm_dai_lb_init
  9. axg_card_add_tdm_loopback
  10. axg_card_parse_daifmt
  11. axg_card_parse_cpu_tdm_slots
  12. axg_card_parse_codecs_masks
  13. axg_card_parse_tdm
  14. axg_card_set_be_link
  15. axg_card_set_fe_link
  16. axg_card_cpu_is_capture_fe
  17. axg_card_cpu_is_playback_fe
  18. axg_card_cpu_is_tdm_iface
  19. axg_card_cpu_is_codec
  20. axg_card_add_link
  21. axg_card_add_links
  22. axg_card_parse_of_optional
  23. axg_card_probe
  24. axg_card_remove

   1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
   2 //
   3 // Copyright (c) 2018 BayLibre, SAS.
   4 // Author: Jerome Brunet <jbrunet@baylibre.com>
   5 
   6 #include <linux/module.h>
   7 #include <linux/of_platform.h>
   8 #include <sound/soc.h>
   9 #include <sound/soc-dai.h>
  10 
  11 #include "axg-tdm.h"
  12 
  13 struct axg_card {
  14         struct snd_soc_card card;
  15         void **link_data;
  16 };
  17 
  18 struct axg_dai_link_tdm_mask {
  19         u32 tx;
  20         u32 rx;
  21 };
  22 
  23 struct axg_dai_link_tdm_data {
  24         unsigned int mclk_fs;
  25         unsigned int slots;
  26         unsigned int slot_width;
  27         u32 *tx_mask;
  28         u32 *rx_mask;
  29         struct axg_dai_link_tdm_mask *codec_masks;
  30 };
  31 
  32 /*
  33  * Base params for the codec to codec links
  34  * Those will be over-written by the CPU side of the link
  35  */
  36 static const struct snd_soc_pcm_stream codec_params = {
  37         .formats = SNDRV_PCM_FMTBIT_S24_LE,
  38         .rate_min = 5525,
  39         .rate_max = 192000,
  40         .channels_min = 1,
  41         .channels_max = 8,
  42 };
  43 
  44 #define PREFIX "amlogic,"
  45 
  46 static int axg_card_reallocate_links(struct axg_card *priv,
  47                                      unsigned int num_links)
  48 {
  49         struct snd_soc_dai_link *links;
  50         void **ldata;
  51 
  52         links = krealloc(priv->card.dai_link,
  53                          num_links * sizeof(*priv->card.dai_link),
  54                          GFP_KERNEL | __GFP_ZERO);
  55         ldata = krealloc(priv->link_data,
  56                          num_links * sizeof(*priv->link_data),
  57                          GFP_KERNEL | __GFP_ZERO);
  58 
  59         if (!links || !ldata) {
  60                 dev_err(priv->card.dev, "failed to allocate links\n");
  61                 return -ENOMEM;
  62         }
  63 
  64         priv->card.dai_link = links;
  65         priv->link_data = ldata;
  66         priv->card.num_links = num_links;
  67         return 0;
  68 }
  69 
  70 static int axg_card_parse_dai(struct snd_soc_card *card,
  71                               struct device_node *node,
  72                               struct device_node **dai_of_node,
  73                               const char **dai_name)
  74 {
  75         struct of_phandle_args args;
  76         int ret;
  77 
  78         if (!dai_name || !dai_of_node || !node)
  79                 return -EINVAL;
  80 
  81         ret = of_parse_phandle_with_args(node, "sound-dai",
  82                                          "#sound-dai-cells", 0, &args);
  83         if (ret) {
  84                 if (ret != -EPROBE_DEFER)
  85                         dev_err(card->dev, "can't parse dai %d\n", ret);
  86                 return ret;
  87         }
  88         *dai_of_node = args.np;
  89 
  90         return snd_soc_get_dai_name(&args, dai_name);
  91 }
  92 
  93 static int axg_card_set_link_name(struct snd_soc_card *card,
  94                                   struct snd_soc_dai_link *link,
  95                                   struct device_node *node,
  96                                   const char *prefix)
  97 {
  98         char *name = devm_kasprintf(card->dev, GFP_KERNEL, "%s.%s",
  99                                     prefix, node->full_name);
 100         if (!name)
 101                 return -ENOMEM;
 102 
 103         link->name = name;
 104         link->stream_name = name;
 105 
 106         return 0;
 107 }
 108 
 109 static void axg_card_clean_references(struct axg_card *priv)
 110 {
 111         struct snd_soc_card *card = &priv->card;
 112         struct snd_soc_dai_link *link;
 113         struct snd_soc_dai_link_component *codec;
 114         struct snd_soc_aux_dev *aux;
 115         int i, j;
 116 
 117         if (card->dai_link) {
 118                 for_each_card_prelinks(card, i, link) {
 119                         if (link->cpus)
 120                                 of_node_put(link->cpus->of_node);
 121                         for_each_link_codecs(link, j, codec)
 122                                 of_node_put(codec->of_node);
 123                 }
 124         }
 125 
 126         if (card->aux_dev) {
 127                 for_each_card_pre_auxs(card, i, aux)
 128                         of_node_put(aux->dlc.of_node);
 129         }
 130 
 131         kfree(card->dai_link);
 132         kfree(priv->link_data);
 133 }
 134 
 135 static int axg_card_add_aux_devices(struct snd_soc_card *card)
 136 {
 137         struct device_node *node = card->dev->of_node;
 138         struct snd_soc_aux_dev *aux;
 139         int num, i;
 140 
 141         num = of_count_phandle_with_args(node, "audio-aux-devs", NULL);
 142         if (num == -ENOENT) {
 143                 /*
 144                  * It is ok to have no auxiliary devices but for this card it
 145                  * is a strange situtation. Let's warn the about it.
 146                  */
 147                 dev_warn(card->dev, "card has no auxiliary devices\n");
 148                 return 0;
 149         } else if (num < 0) {
 150                 dev_err(card->dev, "error getting auxiliary devices: %d\n",
 151                         num);
 152                 return num;
 153         }
 154 
 155         aux = devm_kcalloc(card->dev, num, sizeof(*aux), GFP_KERNEL);
 156         if (!aux)
 157                 return -ENOMEM;
 158         card->aux_dev = aux;
 159         card->num_aux_devs = num;
 160 
 161         for_each_card_pre_auxs(card, i, aux) {
 162                 aux->dlc.of_node =
 163                         of_parse_phandle(node, "audio-aux-devs", i);
 164                 if (!aux->dlc.of_node)
 165                         return -EINVAL;
 166         }
 167 
 168         return 0;
 169 }
 170 
 171 static int axg_card_tdm_be_hw_params(struct snd_pcm_substream *substream,
 172                                      struct snd_pcm_hw_params *params)
 173 {
 174         struct snd_soc_pcm_runtime *rtd = substream->private_data;
 175         struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card);
 176         struct axg_dai_link_tdm_data *be =
 177                 (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num];
 178         struct snd_soc_dai *codec_dai;
 179         unsigned int mclk;
 180         int ret, i;
 181 
 182         if (be->mclk_fs) {
 183                 mclk = params_rate(params) * be->mclk_fs;
 184 
 185                 for_each_rtd_codec_dai(rtd, i, codec_dai) {
 186                         ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 187                                                      SND_SOC_CLOCK_IN);
 188                         if (ret && ret != -ENOTSUPP)
 189                                 return ret;
 190                 }
 191 
 192                 ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk,
 193                                              SND_SOC_CLOCK_OUT);
 194                 if (ret && ret != -ENOTSUPP)
 195                         return ret;
 196         }
 197 
 198         return 0;
 199 }
 200 
 201 static const struct snd_soc_ops axg_card_tdm_be_ops = {
 202         .hw_params = axg_card_tdm_be_hw_params,
 203 };
 204 
 205 static int axg_card_tdm_dai_init(struct snd_soc_pcm_runtime *rtd)
 206 {
 207         struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card);
 208         struct axg_dai_link_tdm_data *be =
 209                 (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num];
 210         struct snd_soc_dai *codec_dai;
 211         int ret, i;
 212 
 213         for_each_rtd_codec_dai(rtd, i, codec_dai) {
 214                 ret = snd_soc_dai_set_tdm_slot(codec_dai,
 215                                                be->codec_masks[i].tx,
 216                                                be->codec_masks[i].rx,
 217                                                be->slots, be->slot_width);
 218                 if (ret && ret != -ENOTSUPP) {
 219                         dev_err(codec_dai->dev,
 220                                 "setting tdm link slots failed\n");
 221                         return ret;
 222                 }
 223         }
 224 
 225         ret = axg_tdm_set_tdm_slots(rtd->cpu_dai, be->tx_mask, be->rx_mask,
 226                                     be->slots, be->slot_width);
 227         if (ret) {
 228                 dev_err(rtd->cpu_dai->dev, "setting tdm link slots failed\n");
 229                 return ret;
 230         }
 231 
 232         return 0;
 233 }
 234 
 235 static int axg_card_tdm_dai_lb_init(struct snd_soc_pcm_runtime *rtd)
 236 {
 237         struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card);
 238         struct axg_dai_link_tdm_data *be =
 239                 (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num];
 240         int ret;
 241 
 242         /* The loopback rx_mask is the pad tx_mask */
 243         ret = axg_tdm_set_tdm_slots(rtd->cpu_dai, NULL, be->tx_mask,
 244                                     be->slots, be->slot_width);
 245         if (ret) {
 246                 dev_err(rtd->cpu_dai->dev, "setting tdm link slots failed\n");
 247                 return ret;
 248         }
 249 
 250         return 0;
 251 }
 252 
 253 static int axg_card_add_tdm_loopback(struct snd_soc_card *card,
 254                                      int *index)
 255 {
 256         struct axg_card *priv = snd_soc_card_get_drvdata(card);
 257         struct snd_soc_dai_link *pad = &card->dai_link[*index];
 258         struct snd_soc_dai_link *lb;
 259         struct snd_soc_dai_link_component *dlc;
 260         int ret;
 261 
 262         /* extend links */
 263         ret = axg_card_reallocate_links(priv, card->num_links + 1);
 264         if (ret)
 265                 return ret;
 266 
 267         lb = &card->dai_link[*index + 1];
 268 
 269         lb->name = kasprintf(GFP_KERNEL, "%s-lb", pad->name);
 270         if (!lb->name)
 271                 return -ENOMEM;
 272 
 273         dlc = devm_kzalloc(card->dev, 2 * sizeof(*dlc), GFP_KERNEL);
 274         if (!dlc)
 275                 return -ENOMEM;
 276 
 277         lb->cpus = &dlc[0];
 278         lb->codecs = &dlc[1];
 279         lb->num_cpus = 1;
 280         lb->num_codecs = 1;
 281 
 282         lb->stream_name = lb->name;
 283         lb->cpus->of_node = pad->cpus->of_node;
 284         lb->cpus->dai_name = "TDM Loopback";
 285         lb->codecs->name = "snd-soc-dummy";
 286         lb->codecs->dai_name = "snd-soc-dummy-dai";
 287         lb->dpcm_capture = 1;
 288         lb->no_pcm = 1;
 289         lb->ops = &axg_card_tdm_be_ops;
 290         lb->init = axg_card_tdm_dai_lb_init;
 291 
 292         /* Provide the same link data to the loopback */
 293         priv->link_data[*index + 1] = priv->link_data[*index];
 294 
 295         /*
 296          * axg_card_clean_references() will iterate over this link,
 297          * make sure the node count is balanced
 298          */
 299         of_node_get(lb->cpus->of_node);
 300 
 301         /* Let add_links continue where it should */
 302         *index += 1;
 303 
 304         return 0;
 305 }
 306 
 307 static unsigned int axg_card_parse_daifmt(struct device_node *node,
 308                                           struct device_node *cpu_node)
 309 {
 310         struct device_node *bitclkmaster = NULL;
 311         struct device_node *framemaster = NULL;
 312         unsigned int daifmt;
 313 
 314         daifmt = snd_soc_of_parse_daifmt(node, PREFIX,
 315                                          &bitclkmaster, &framemaster);
 316         daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
 317 
 318         /* If no master is provided, default to cpu master */
 319         if (!bitclkmaster || bitclkmaster == cpu_node) {
 320                 daifmt |= (!framemaster || framemaster == cpu_node) ?
 321                         SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBS_CFM;
 322         } else {
 323                 daifmt |= (!framemaster || framemaster == cpu_node) ?
 324                         SND_SOC_DAIFMT_CBM_CFS : SND_SOC_DAIFMT_CBM_CFM;
 325         }
 326 
 327         of_node_put(bitclkmaster);
 328         of_node_put(framemaster);
 329 
 330         return daifmt;
 331 }
 332 
 333 static int axg_card_parse_cpu_tdm_slots(struct snd_soc_card *card,
 334                                         struct snd_soc_dai_link *link,
 335                                         struct device_node *node,
 336                                         struct axg_dai_link_tdm_data *be)
 337 {
 338         char propname[32];
 339         u32 tx, rx;
 340         int i;
 341 
 342         be->tx_mask = devm_kcalloc(card->dev, AXG_TDM_NUM_LANES,
 343                                    sizeof(*be->tx_mask), GFP_KERNEL);
 344         be->rx_mask = devm_kcalloc(card->dev, AXG_TDM_NUM_LANES,
 345                                    sizeof(*be->rx_mask), GFP_KERNEL);
 346         if (!be->tx_mask || !be->rx_mask)
 347                 return -ENOMEM;
 348 
 349         for (i = 0, tx = 0; i < AXG_TDM_NUM_LANES; i++) {
 350                 snprintf(propname, 32, "dai-tdm-slot-tx-mask-%d", i);
 351                 snd_soc_of_get_slot_mask(node, propname, &be->tx_mask[i]);
 352                 tx = max(tx, be->tx_mask[i]);
 353         }
 354 
 355         /* Disable playback is the interface has no tx slots */
 356         if (!tx)
 357                 link->dpcm_playback = 0;
 358 
 359         for (i = 0, rx = 0; i < AXG_TDM_NUM_LANES; i++) {
 360                 snprintf(propname, 32, "dai-tdm-slot-rx-mask-%d", i);
 361                 snd_soc_of_get_slot_mask(node, propname, &be->rx_mask[i]);
 362                 rx = max(rx, be->rx_mask[i]);
 363         }
 364 
 365         /* Disable capture is the interface has no rx slots */
 366         if (!rx)
 367                 link->dpcm_capture = 0;
 368 
 369         /* ... but the interface should at least have one of them */
 370         if (!tx && !rx) {
 371                 dev_err(card->dev, "tdm link has no cpu slots\n");
 372                 return -EINVAL;
 373         }
 374 
 375         of_property_read_u32(node, "dai-tdm-slot-num", &be->slots);
 376         if (!be->slots) {
 377                 /*
 378                  * If the slot number is not provided, set it such as it
 379                  * accommodates the largest mask
 380                  */
 381                 be->slots = fls(max(tx, rx));
 382         } else if (be->slots < fls(max(tx, rx)) || be->slots > 32) {
 383                 /*
 384                  * Error if the slots can't accommodate the largest mask or
 385                  * if it is just too big
 386                  */
 387                 dev_err(card->dev, "bad slot number\n");
 388                 return -EINVAL;
 389         }
 390 
 391         of_property_read_u32(node, "dai-tdm-slot-width", &be->slot_width);
 392 
 393         return 0;
 394 }
 395 
 396 static int axg_card_parse_codecs_masks(struct snd_soc_card *card,
 397                                        struct snd_soc_dai_link *link,
 398                                        struct device_node *node,
 399                                        struct axg_dai_link_tdm_data *be)
 400 {
 401         struct axg_dai_link_tdm_mask *codec_mask;
 402         struct device_node *np;
 403 
 404         codec_mask = devm_kcalloc(card->dev, link->num_codecs,
 405                                   sizeof(*codec_mask), GFP_KERNEL);
 406         if (!codec_mask)
 407                 return -ENOMEM;
 408 
 409         be->codec_masks = codec_mask;
 410 
 411         for_each_child_of_node(node, np) {
 412                 snd_soc_of_get_slot_mask(np, "dai-tdm-slot-rx-mask",
 413                                          &codec_mask->rx);
 414                 snd_soc_of_get_slot_mask(np, "dai-tdm-slot-tx-mask",
 415                                          &codec_mask->tx);
 416 
 417                 codec_mask++;
 418         }
 419 
 420         return 0;
 421 }
 422 
 423 static int axg_card_parse_tdm(struct snd_soc_card *card,
 424                               struct device_node *node,
 425                               int *index)
 426 {
 427         struct axg_card *priv = snd_soc_card_get_drvdata(card);
 428         struct snd_soc_dai_link *link = &card->dai_link[*index];
 429         struct axg_dai_link_tdm_data *be;
 430         int ret;
 431 
 432         /* Allocate tdm link parameters */
 433         be = devm_kzalloc(card->dev, sizeof(*be), GFP_KERNEL);
 434         if (!be)
 435                 return -ENOMEM;
 436         priv->link_data[*index] = be;
 437 
 438         /* Setup tdm link */
 439         link->ops = &axg_card_tdm_be_ops;
 440         link->init = axg_card_tdm_dai_init;
 441         link->dai_fmt = axg_card_parse_daifmt(node, link->cpus->of_node);
 442 
 443         of_property_read_u32(node, "mclk-fs", &be->mclk_fs);
 444 
 445         ret = axg_card_parse_cpu_tdm_slots(card, link, node, be);
 446         if (ret) {
 447                 dev_err(card->dev, "error parsing tdm link slots\n");
 448                 return ret;
 449         }
 450 
 451         ret = axg_card_parse_codecs_masks(card, link, node, be);
 452         if (ret)
 453                 return ret;
 454 
 455         /* Add loopback if the pad dai has playback */
 456         if (link->dpcm_playback) {
 457                 ret = axg_card_add_tdm_loopback(card, index);
 458                 if (ret)
 459                         return ret;
 460         }
 461 
 462         return 0;
 463 }
 464 
 465 static int axg_card_set_be_link(struct snd_soc_card *card,
 466                                 struct snd_soc_dai_link *link,
 467                                 struct device_node *node)
 468 {
 469         struct snd_soc_dai_link_component *codec;
 470         struct device_node *np;
 471         int ret, num_codecs;
 472 
 473         link->no_pcm = 1;
 474         link->dpcm_playback = 1;
 475         link->dpcm_capture = 1;
 476 
 477         num_codecs = of_get_child_count(node);
 478         if (!num_codecs) {
 479                 dev_err(card->dev, "be link %s has no codec\n",
 480                         node->full_name);
 481                 return -EINVAL;
 482         }
 483 
 484         codec = devm_kcalloc(card->dev, num_codecs, sizeof(*codec), GFP_KERNEL);
 485         if (!codec)
 486                 return -ENOMEM;
 487 
 488         link->codecs = codec;
 489         link->num_codecs = num_codecs;
 490 
 491         for_each_child_of_node(node, np) {
 492                 ret = axg_card_parse_dai(card, np, &codec->of_node,
 493                                          &codec->dai_name);
 494                 if (ret) {
 495                         of_node_put(np);
 496                         return ret;
 497                 }
 498 
 499                 codec++;
 500         }
 501 
 502         ret = axg_card_set_link_name(card, link, node, "be");
 503         if (ret)
 504                 dev_err(card->dev, "error setting %pOFn link name\n", np);
 505 
 506         return ret;
 507 }
 508 
 509 static int axg_card_set_fe_link(struct snd_soc_card *card,
 510                                 struct snd_soc_dai_link *link,
 511                                 struct device_node *node,
 512                                 bool is_playback)
 513 {
 514         struct snd_soc_dai_link_component *codec;
 515 
 516         codec = devm_kzalloc(card->dev, sizeof(*codec), GFP_KERNEL);
 517         if (!codec)
 518                 return -ENOMEM;
 519 
 520         link->codecs = codec;
 521         link->num_codecs = 1;
 522 
 523         link->dynamic = 1;
 524         link->dpcm_merged_format = 1;
 525         link->dpcm_merged_chan = 1;
 526         link->dpcm_merged_rate = 1;
 527         link->codecs->dai_name = "snd-soc-dummy-dai";
 528         link->codecs->name = "snd-soc-dummy";
 529 
 530         if (is_playback)
 531                 link->dpcm_playback = 1;
 532         else
 533                 link->dpcm_capture = 1;
 534 
 535         return axg_card_set_link_name(card, link, node, "fe");
 536 }
 537 
 538 static int axg_card_cpu_is_capture_fe(struct device_node *np)
 539 {
 540         return of_device_is_compatible(np, PREFIX "axg-toddr");
 541 }
 542 
 543 static int axg_card_cpu_is_playback_fe(struct device_node *np)
 544 {
 545         return of_device_is_compatible(np, PREFIX "axg-frddr");
 546 }
 547 
 548 static int axg_card_cpu_is_tdm_iface(struct device_node *np)
 549 {
 550         return of_device_is_compatible(np, PREFIX "axg-tdm-iface");
 551 }
 552 
 553 static int axg_card_cpu_is_codec(struct device_node *np)
 554 {
 555         return of_device_is_compatible(np, PREFIX "g12a-tohdmitx");
 556 }
 557 
 558 static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np,
 559                              int *index)
 560 {
 561         struct snd_soc_dai_link *dai_link = &card->dai_link[*index];
 562         struct snd_soc_dai_link_component *cpu;
 563         int ret;
 564 
 565         cpu = devm_kzalloc(card->dev, sizeof(*cpu), GFP_KERNEL);
 566         if (!cpu)
 567                 return -ENOMEM;
 568 
 569         dai_link->cpus = cpu;
 570         dai_link->num_cpus = 1;
 571 
 572         ret = axg_card_parse_dai(card, np, &dai_link->cpus->of_node,
 573                                  &dai_link->cpus->dai_name);
 574         if (ret)
 575                 return ret;
 576 
 577         if (axg_card_cpu_is_playback_fe(dai_link->cpus->of_node))
 578                 ret = axg_card_set_fe_link(card, dai_link, np, true);
 579         else if (axg_card_cpu_is_capture_fe(dai_link->cpus->of_node))
 580                 ret = axg_card_set_fe_link(card, dai_link, np, false);
 581         else
 582                 ret = axg_card_set_be_link(card, dai_link, np);
 583 
 584         if (ret)
 585                 return ret;
 586 
 587         if (axg_card_cpu_is_tdm_iface(dai_link->cpus->of_node))
 588                 ret = axg_card_parse_tdm(card, np, index);
 589         else if (axg_card_cpu_is_codec(dai_link->cpus->of_node))
 590                 dai_link->params = &codec_params;
 591 
 592         return ret;
 593 }
 594 
 595 static int axg_card_add_links(struct snd_soc_card *card)
 596 {
 597         struct axg_card *priv = snd_soc_card_get_drvdata(card);
 598         struct device_node *node = card->dev->of_node;
 599         struct device_node *np;
 600         int num, i, ret;
 601 
 602         num = of_get_child_count(node);
 603         if (!num) {
 604                 dev_err(card->dev, "card has no links\n");
 605                 return -EINVAL;
 606         }
 607 
 608         ret = axg_card_reallocate_links(priv, num);
 609         if (ret)
 610                 return ret;
 611 
 612         i = 0;
 613         for_each_child_of_node(node, np) {
 614                 ret = axg_card_add_link(card, np, &i);
 615                 if (ret) {
 616                         of_node_put(np);
 617                         return ret;
 618                 }
 619 
 620                 i++;
 621         }
 622 
 623         return 0;
 624 }
 625 
 626 static int axg_card_parse_of_optional(struct snd_soc_card *card,
 627                                       const char *propname,
 628                                       int (*func)(struct snd_soc_card *c,
 629                                                   const char *p))
 630 {
 631         /* If property is not provided, don't fail ... */
 632         if (!of_property_read_bool(card->dev->of_node, propname))
 633                 return 0;
 634 
 635         /* ... but do fail if it is provided and the parsing fails */
 636         return func(card, propname);
 637 }
 638 
 639 static const struct of_device_id axg_card_of_match[] = {
 640         { .compatible = "amlogic,axg-sound-card", },
 641         {}
 642 };
 643 MODULE_DEVICE_TABLE(of, axg_card_of_match);
 644 
 645 static int axg_card_probe(struct platform_device *pdev)
 646 {
 647         struct device *dev = &pdev->dev;
 648         struct axg_card *priv;
 649         int ret;
 650 
 651         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 652         if (!priv)
 653                 return -ENOMEM;
 654 
 655         platform_set_drvdata(pdev, priv);
 656         snd_soc_card_set_drvdata(&priv->card, priv);
 657 
 658         priv->card.owner = THIS_MODULE;
 659         priv->card.dev = dev;
 660 
 661         ret = snd_soc_of_parse_card_name(&priv->card, "model");
 662         if (ret < 0)
 663                 return ret;
 664 
 665         ret = axg_card_parse_of_optional(&priv->card, "audio-routing",
 666                                          snd_soc_of_parse_audio_routing);
 667         if (ret) {
 668                 dev_err(dev, "error while parsing routing\n");
 669                 return ret;
 670         }
 671 
 672         ret = axg_card_parse_of_optional(&priv->card, "audio-widgets",
 673                                          snd_soc_of_parse_audio_simple_widgets);
 674         if (ret) {
 675                 dev_err(dev, "error while parsing widgets\n");
 676                 return ret;
 677         }
 678 
 679         ret = axg_card_add_links(&priv->card);
 680         if (ret)
 681                 goto out_err;
 682 
 683         ret = axg_card_add_aux_devices(&priv->card);
 684         if (ret)
 685                 goto out_err;
 686 
 687         ret = devm_snd_soc_register_card(dev, &priv->card);
 688         if (ret)
 689                 goto out_err;
 690 
 691         return 0;
 692 
 693 out_err:
 694         axg_card_clean_references(priv);
 695         return ret;
 696 }
 697 
 698 static int axg_card_remove(struct platform_device *pdev)
 699 {
 700         struct axg_card *priv = platform_get_drvdata(pdev);
 701 
 702         axg_card_clean_references(priv);
 703 
 704         return 0;
 705 }
 706 
 707 static struct platform_driver axg_card_pdrv = {
 708         .probe = axg_card_probe,
 709         .remove = axg_card_remove,
 710         .driver = {
 711                 .name = "axg-sound-card",
 712                 .of_match_table = axg_card_of_match,
 713         },
 714 };
 715 module_platform_driver(axg_card_pdrv);
 716 
 717 MODULE_DESCRIPTION("Amlogic AXG ALSA machine driver");
 718 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
 719 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */