Linux Kernel Machine Driver Basics-Free Linux Device Drivers Course

Linux Kernel Machine Driver Basics
Free Linux Kernel Development Course — How Sound Cards Come Together in Linux

If you have followed this free linux kernel development course so far, you already know how a codec driver talks to an audio chip, and how a platform driver moves audio data using DMA. But if you plug a board with both of these drivers loaded, you still will not hear any sound. Something is missing — a driver that tells the kernel “this codec chip is connected to this CPU audio interface, now make a sound card out of them.” That missing piece is called a linux kernel machine driver, and it is what this lecture explains in the simplest way possible.

This is a beginner-friendly lecture, part of our free linux device drivers course. We will keep the explanation simple, use the latest kernel APIs (not the outdated ones you may find in old books), and walk through one small original example you can actually build and test.

linux kernel machine driver ASoC sound card free linux device drivers course free embedded systems course free embedded linux course

What You Will Learn

  • Why a Linux sound card needs a machine driver, in plain simple terms
  • What a “DAI link” means — described without any confusing jargon
  • The basic parts of a modern snd_soc_dai_link and snd_soc_card
  • How to write a very small, original example machine driver
  • How to build it, load it, and see the expected output

Prerequisites

  • Basic idea of what a Linux kernel module is
  • Basic idea of Device Tree nodes (we keep this part very light)
  • A Linux machine or board with kernel headers installed, to build and test the example

Why Do We Need a Machine Driver?

Think of audio hardware on a board as two separate people who do not speak the same language. One person is the codec chip — it knows how to turn digital numbers into sound and back again. The other person is the CPU audio interface — it knows how to move those digital numbers around using DMA. Both are experts at their own job, but neither one knows the other exists.

The linux kernel machine driver is the translator standing between them. It does not process audio itself. Its only job is to say: “this codec’s audio pins are wired to this CPU’s audio pins, on this particular board.” Once it says that, the kernel can finally combine both sides into one working sound card that shows up in aplay -l.

Who Talks to Whom
Codec DriverMachine DriverPlatform Driver

This is exactly why machine drivers are almost always board-specific. A codec driver can be reused on any board that has the same chip. A platform driver can be reused on any board that has the same CPU. But the wiring between them — which pin goes where — is unique to each board, so the machine driver is usually written fresh for each board (or generated from Device Tree, which we will touch on briefly at the end).

The DAI Link — In Simple Words

A “DAI” is just the audio interface pins on a chip (Digital Audio Interface). A “DAI link” is simply the statement: “this DAI on the codec is connected to that DAI on the CPU.” The Linux kernel stores this statement in a structure called struct snd_soc_dai_link.

In older kernels, this structure used simple name-based fields like codec_name and cpu_dai_name. Modern kernels have moved to a cleaner, array-based style, because it also allows one link to connect to more than one codec at a time. As a student, the important fields to remember for now are just these four:

The Four Fields That Matter Most
name cpus[] codecs[] platforms[]
  • name — just a label so you and the kernel can identify this link
  • cpus[] — which CPU DAI this link uses
  • codecs[] — which codec DAI this link uses (can be more than one codec)
  • platforms[] — which platform (DMA) driver handles the data movement

Everything else — clocking, GPIO amplifier control, DAPM routing — builds on top of this basic link, and we will cover those step by step in the next lectures of this free linux kernel development course.

A Very Small Example

Let’s write the smallest possible machine driver. It does one thing only — it creates a sound card with one DAI link. We are not adding clocking, GPIOs, or DAPM yet, so the concept stays clear. Everything below is an original example for this course, not copied from any book.

// ep_simple_machine.c - a very small, original ASoC machine driver
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <sound/soc.h>

SND_SOC_DAILINK_DEFS(ep_link,
    DAILINK_COMP_ARRAY(COMP_EMPTY()),
    DAILINK_COMP_ARRAY(COMP_EMPTY()),
    DAILINK_COMP_ARRAY(COMP_EMPTY()));

static struct snd_soc_dai_link ep_dai_link = {
    .name = "ep-simple-link",
    .stream_name = "ep-simple-audio",
    SND_SOC_DAILINK_REG(ep_link),
};

static struct snd_soc_card ep_card = {
    .name = "ep-simple-card",
    .owner = THIS_MODULE,
    .dai_link = &ep_dai_link,
    .num_links = 1,
};

static int ep_simple_probe(struct platform_device *pdev)
{
    ep_dai_link.cpus->of_node = of_parse_phandle(pdev->dev.of_node, "ep,cpu", 0);
    ep_dai_link.platforms->of_node = ep_dai_link.cpus->of_node;
    ep_dai_link.codecs->of_node = of_parse_phandle(pdev->dev.of_node, "ep,codec", 0);
    ep_dai_link.codecs->dai_name = "ep-codec-dai";

    ep_card.dev = &pdev->dev;
    return devm_snd_soc_register_card(&pdev->dev, &ep_card);
}

static const struct of_device_id ep_simple_of_match[] = {
    { .compatible = "ep,simple-audio" },
    { }
};
MODULE_DEVICE_TABLE(of, ep_simple_of_match);

static struct platform_driver ep_simple_driver = {
    .driver = {
        .name = "ep-simple-audio",
        .of_match_table = ep_simple_of_match,
    },
    .probe = ep_simple_probe,
};
module_platform_driver(ep_simple_driver);

MODULE_DESCRIPTION("EmbeddedPathashala simple ASoC machine driver example");
MODULE_LICENSE("GPL");

Matching Device Tree snippet — this is just telling the driver which two nodes to connect:

sound {
    compatible = "ep,simple-audio";
    ep,cpu = &ep_cpu_dai;
    ep,codec = &ep_codec;
};

Build, Load, and Expected Output

Build the module against your running kernel:

$ make -C /lib/modules/$(uname -r)/build M=$PWD modules
$ sudo insmod ep_simple_machine.ko

Check that the card was registered:

$ dmesg | tail -n 3
[   9.802113] ep-simple-audio sound: ep-simple-link <-> ep-codec-dai mapping ok
[   9.802650] ep-simple-audio sound: ep-simple-card registered

$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: epsimplecard [ep-simple-card], device 0: ep-simple-link ep-cpu-dai-0 [ep-simple-link ep-cpu-dai-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

That is it — the moment aplay -l shows ep-simple-card, you have successfully connected a codec and a CPU DAI using a machine driver. This is the same basic pattern every real machine driver in the kernel follows, just with more configuration added on top.

Common Mistakes Beginners Make

  • Expecting sound immediately. A registered card only means the wiring is described correctly — clocking and DAPM routing (covered in later lectures) are still needed for actual audio to flow.
  • Forgetting the Device Tree phandles. If ep,cpu or ep,codec is missing or misspelled, the driver will fail to find the nodes and probe will fail silently.
  • Mixing old and new struct fields. Stick to the modern cpus[]/codecs[]/platforms[] style shown here — don’t mix it with older single-pointer fields from outdated examples.

Best Practices

  • Keep your machine driver small and focused only on wiring — push anything reusable back into the codec or platform driver.
  • Always use Device Tree phandles instead of hardcoded string names to find your CPU and codec nodes.
  • Use devm_snd_soc_register_card() so the kernel handles cleanup automatically if something fails.

Summary

A machine driver is simply the piece that connects a codec driver and a platform driver into one working Linux sound card. It does this using a snd_soc_dai_link, wrapped inside a snd_soc_card. In this lecture of our free embedded linux course, we kept things as simple as possible — one link, one codec, one CPU DAI — so the core idea is clear before we add clocking, amplifier control, and DAPM routing in the lectures ahead. If you followed along and saw your own ep-simple-card appear in aplay -l, you now understand the heart of how every Linux sound card comes together.

FAQ

What is a machine driver in simple terms?

It is the small driver that tells the Linux kernel which codec chip is connected to which CPU audio interface on a specific board, so both can be combined into one working sound card.

Do I need to understand codec and platform drivers before this lecture?

A basic idea helps, but this lecture is written so a beginner in our free linux kernel development course can follow it even with only a light background in those topics.

Why does the example not produce any actual sound?

The example only proves that the machine driver correctly registered a sound card. Real audio also needs clocking and DAPM routing, which are covered in the next lectures of this free linux device drivers course.

Why use cpus[], codecs[], and platforms[] instead of the older fields?

These array-based fields are the modern kernel style and also allow a single DAI link to connect to more than one codec, which the older single-pointer fields could not do.

Can a board work without writing a custom machine driver?

Yes, for simple single-codec boards, a generic driver can sometimes describe the wiring purely from Device Tree. We will look at that option later in this free embedded systems course.

Leave a Reply

Your email address will not be published. Required fields are marked *