static int pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_motu *motu = substream->private_data;
-       const struct snd_motu_protocol *const protocol = motu->spec->protocol;
        struct amdtp_domain *d = &motu->domain;
        enum snd_motu_clock_source src;
        int err;
        if (err < 0)
                goto err_locked;
 
-       err = protocol->get_clock_source(motu, &src);
+       err = snd_motu_protocol_get_clock_source(motu, &src);
        if (err < 0)
                goto err_locked;
 
                unsigned int frames_per_buffer = d->events_per_buffer;
                unsigned int rate;
 
-               err = protocol->get_clock_rate(motu, &rate);
+               err = snd_motu_protocol_get_clock_rate(motu, &rate);
                if (err < 0)
                        goto err_locked;
 
 
 {
 
        struct snd_motu *motu = entry->private_data;
-       const struct snd_motu_protocol *const protocol = motu->spec->protocol;
        unsigned int rate;
        enum snd_motu_clock_source source;
 
-       if (protocol->get_clock_rate(motu, &rate) < 0)
+       if (snd_motu_protocol_get_clock_rate(motu, &rate) < 0)
                return;
-       if (protocol->get_clock_source(motu, &source) < 0)
+       if (snd_motu_protocol_get_clock_source(motu, &source) < 0)
                return;
 
        snd_iprintf(buffer, "Rate:\t%d\n", rate);
                             struct snd_info_buffer *buffer)
 {
        struct snd_motu *motu = entry->private_data;
-       const struct snd_motu_protocol *const protocol = motu->spec->protocol;
        unsigned int mode;
        struct snd_motu_packet_format *formats;
        int i;
 
-       if (protocol->cache_packet_formats(motu) < 0)
+       if (snd_motu_protocol_cache_packet_formats(motu) < 0)
                return;
 
        snd_iprintf(buffer, "tx:\tmsg\tfixed\tdiffered\n");
 
        return 0;
 }
 
-static int v2_get_clock_rate(struct snd_motu *motu, unsigned int *rate)
+int snd_motu_protocol_v2_get_clock_rate(struct snd_motu *motu,
+                                       unsigned int *rate)
 {
        __be32 reg;
        int err;
        return get_clock_rate(be32_to_cpu(reg), rate);
 }
 
-static int v2_set_clock_rate(struct snd_motu *motu, unsigned int rate)
+int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu,
+                                       unsigned int rate)
 {
        __be32 reg;
        u32 data;
        return 0;
 }
 
-static int v2_get_clock_source(struct snd_motu *motu,
-                              enum snd_motu_clock_source *src)
+int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu,
+                                         enum snd_motu_clock_source *src)
 {
        __be32 reg;
        int err;
        return get_clock_source(motu, be32_to_cpu(reg), src);
 }
 
-static int v2_switch_fetching_mode(struct snd_motu *motu, bool enable)
+int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu,
+                                             bool enable)
 {
        enum snd_motu_clock_source src;
        __be32 reg;
        formats->differed_part_pcm_chunks[1] = pcm_chunks[1];
 }
 
-static int v2_cache_packet_formats(struct snd_motu *motu)
+int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu)
 {
        __be32 reg;
        u32 data;
 }
 
 static const struct snd_motu_protocol snd_motu_protocol_v2 = {
-       .get_clock_rate         = v2_get_clock_rate,
-       .set_clock_rate         = v2_set_clock_rate,
-       .get_clock_source       = v2_get_clock_source,
-       .switch_fetching_mode   = v2_switch_fetching_mode,
-       .cache_packet_formats   = v2_cache_packet_formats,
 };
 
 const struct snd_motu_spec snd_motu_spec_828mk2 = {
 
 #define  V3_NO_ADAT_OPT_OUT_IFACE_A    0x00040000
 #define  V3_NO_ADAT_OPT_OUT_IFACE_B    0x00400000
 
-static int v3_get_clock_rate(struct snd_motu *motu, unsigned int *rate)
+int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu,
+                                       unsigned int *rate)
 {
        __be32 reg;
        u32 data;
        return 0;
 }
 
-static int v3_set_clock_rate(struct snd_motu *motu, unsigned int rate)
+int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu,
+                                       unsigned int rate)
 {
        __be32 reg;
        u32 data;
        return 0;
 }
 
-static int v3_get_clock_source(struct snd_motu *motu,
-                              enum snd_motu_clock_source *src)
+int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu,
+                                         enum snd_motu_clock_source *src)
 {
        __be32 reg;
        u32 data;
        return 0;
 }
 
-static int v3_switch_fetching_mode(struct snd_motu *motu, bool enable)
+int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu,
+                                             bool enable)
 {
        __be32 reg;
        u32 data;
        }
 }
 
-static int v3_cache_packet_formats(struct snd_motu *motu)
+int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu)
 {
        __be32 reg;
        u32 data;
 }
 
 static const struct snd_motu_protocol snd_motu_protocol_v3 = {
-       .get_clock_rate         = v3_get_clock_rate,
-       .set_clock_rate         = v3_set_clock_rate,
-       .get_clock_source       = v3_get_clock_source,
-       .switch_fetching_mode   = v3_switch_fetching_mode,
-       .cache_packet_formats   = v3_cache_packet_formats,
 };
 
 const struct snd_motu_spec snd_motu_spec_828mk3 = {
 
        u32 data;
        int err;
 
-       err = motu->spec->protocol->switch_fetching_mode(motu, false);
+       err = snd_motu_protocol_switch_fetching_mode(motu, false);
        if (err < 0)
                return;
 
 {
        int err;
 
-       err = motu->spec->protocol->cache_packet_formats(motu);
+       err = snd_motu_protocol_cache_packet_formats(motu);
        if (err < 0)
                return err;
 
        unsigned int curr_rate;
        int err;
 
-       err = motu->spec->protocol->get_clock_rate(motu, &curr_rate);
+       err = snd_motu_protocol_get_clock_rate(motu, &curr_rate);
        if (err < 0)
                return err;
        if (rate == 0)
                fw_iso_resources_free(&motu->tx_resources);
                fw_iso_resources_free(&motu->rx_resources);
 
-               err = motu->spec->protocol->set_clock_rate(motu, rate);
+               err = snd_motu_protocol_set_clock_rate(motu, rate);
                if (err < 0) {
                        dev_err(&motu->unit->device,
                                "fail to set sampling rate: %d\n", err);
                        goto stop_streams;
                }
 
-               err = motu->spec->protocol->switch_fetching_mode(motu, true);
+               err = snd_motu_protocol_switch_fetching_mode(motu, true);
                if (err < 0) {
                        dev_err(&motu->unit->device,
                                "fail to enable frame fetching: %d\n", err);
 
 int snd_motu_create_midi_devices(struct snd_motu *motu);
 
 int snd_motu_create_hwdep_device(struct snd_motu *motu);
+
+int snd_motu_protocol_v2_get_clock_rate(struct snd_motu *motu,
+                                       unsigned int *rate);
+int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu,
+                                       unsigned int rate);
+int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu,
+                                         enum snd_motu_clock_source *src);
+int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu,
+                                             bool enable);
+int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu);
+
+int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu,
+                                       unsigned int *rate);
+int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu,
+                                       unsigned int rate);
+int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu,
+                                         enum snd_motu_clock_source *src);
+int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu,
+                                             bool enable);
+int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu);
+
+static inline int snd_motu_protocol_get_clock_rate(struct snd_motu *motu,
+                                                  unsigned int *rate)
+{
+       if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
+               return snd_motu_protocol_v2_get_clock_rate(motu, rate);
+       else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
+               return snd_motu_protocol_v3_get_clock_rate(motu, rate);
+       else
+               return -ENXIO;
+}
+
+static inline int snd_motu_protocol_set_clock_rate(struct snd_motu *motu,
+                                                  unsigned int rate)
+{
+       if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
+               return snd_motu_protocol_v2_set_clock_rate(motu, rate);
+       else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
+               return snd_motu_protocol_v3_set_clock_rate(motu, rate);
+       else
+               return -ENXIO;
+}
+
+static inline int snd_motu_protocol_get_clock_source(struct snd_motu *motu,
+                                       enum snd_motu_clock_source *source)
+{
+       if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
+               return snd_motu_protocol_v2_get_clock_source(motu, source);
+       else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
+               return snd_motu_protocol_v3_get_clock_source(motu, source);
+       else
+               return -ENXIO;
+}
+
+static inline int snd_motu_protocol_switch_fetching_mode(struct snd_motu *motu,
+                                                        bool enable)
+{
+       if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
+               return snd_motu_protocol_v2_switch_fetching_mode(motu, enable);
+       else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
+               return snd_motu_protocol_v3_switch_fetching_mode(motu, enable);
+       else
+               return -ENXIO;
+}
+
+static inline int snd_motu_protocol_cache_packet_formats(struct snd_motu *motu)
+{
+       if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
+               return snd_motu_protocol_v2_cache_packet_formats(motu);
+       else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
+               return snd_motu_protocol_v3_cache_packet_formats(motu);
+       else
+               return -ENXIO;
+}
+
 #endif