Ignore:
Timestamp:
Jul 5, 2010, 11:51:20 AM (15 years ago)
Author:
Paul Smedley
Message:

Update Uniaud32-2.1.x branch with necessary changes for ALSA 1.0.23

File:
1 edited

Legend:

Unmodified
Added
Removed
  • GPL/branches/uniaud32-2.1.x/alsa-kernel/drivers/dummy.c

    r410 r499  
    2626#include <linux/time.h>
    2727#include <linux/wait.h>
     28#include <linux/hrtimer.h>
     29#include <linux/math64.h>
    2830#include <linux/moduleparam.h>
    2931#include <sound/core.h>
     
    3234#include <sound/pcm.h>
    3335#include <sound/rawmidi.h>
     36#include <sound/info.h>
    3437#include <sound/initval.h>
    3538
     
    4043
    4144#define MAX_PCM_DEVICES         4
    42 #define MAX_PCM_SUBSTREAMS      16
     45#define MAX_PCM_SUBSTREAMS      128
    4346#define MAX_MIDI_DEVICES        2
    4447
    45 #if 0 /* emu10k1 emulation */
    46 #define MAX_BUFFER_SIZE         (128 * 1024)
     48/* defaults */
     49#define MAX_BUFFER_SIZE         (64*1024)
     50#define MIN_PERIOD_SIZE         64
     51#define MAX_PERIOD_SIZE         MAX_BUFFER_SIZE
     52#define USE_FORMATS             (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
     53#define USE_RATE                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000
     54#define USE_RATE_MIN            5500
     55#define USE_RATE_MAX            48000
     56#define USE_CHANNELS_MIN        1
     57#define USE_CHANNELS_MAX        2
     58#define USE_PERIODS_MIN         1
     59#define USE_PERIODS_MAX         1024
     60
     61static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;      /* Index 0-MAX */
     62static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;       /* ID for this card */
     63static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
     64static char *model[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = NULL};
     65static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
     66static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};
     67//static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
     68#ifdef CONFIG_HIGH_RES_TIMERS
     69static int hrtimer = 1;
     70#endif
     71static int fake_buffer = 1;
     72
     73module_param_array(index, int, NULL, 0444);
     74MODULE_PARM_DESC(index, "Index value for dummy soundcard.");
     75module_param_array(id, charp, NULL, 0444);
     76MODULE_PARM_DESC(id, "ID string for dummy soundcard.");
     77module_param_array(enable, bool, NULL, 0444);
     78MODULE_PARM_DESC(enable, "Enable this dummy soundcard.");
     79module_param_array(model, charp, NULL, 0444);
     80MODULE_PARM_DESC(model, "Soundcard model.");
     81module_param_array(pcm_devs, int, NULL, 0444);
     82MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver.");
     83module_param_array(pcm_substreams, int, NULL, 0444);
     84MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver.");
     85//module_param_array(midi_devs, int, NULL, 0444);
     86//MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
     87module_param(fake_buffer, bool, 0444);
     88MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");
     89#ifdef CONFIG_HIGH_RES_TIMERS
     90module_param(hrtimer, bool, 0644);
     91MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source.");
     92#endif
     93
     94static struct platform_device *devices[SNDRV_CARDS];
     95
     96#define MIXER_ADDR_MASTER       0
     97#define MIXER_ADDR_LINE         1
     98#define MIXER_ADDR_MIC          2
     99#define MIXER_ADDR_SYNTH        3
     100#define MIXER_ADDR_CD           4
     101#define MIXER_ADDR_LAST         4
     102
     103struct dummy_timer_ops {
     104        int (*create)(struct snd_pcm_substream *);
     105        void (*free)(struct snd_pcm_substream *);
     106        int (*prepare)(struct snd_pcm_substream *);
     107        int (*start)(struct snd_pcm_substream *);
     108        int (*stop)(struct snd_pcm_substream *);
     109        snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
     110};
     111
     112struct dummy_model {
     113        const char *name;
     114        int (*playback_constraints)(struct snd_pcm_runtime *runtime);
     115        int (*capture_constraints)(struct snd_pcm_runtime *runtime);
     116        u64 formats;
     117        size_t buffer_bytes_max;
     118        size_t period_bytes_min;
     119        size_t period_bytes_max;
     120        unsigned int periods_min;
     121        unsigned int periods_max;
     122        unsigned int rates;
     123        unsigned int rate_min;
     124        unsigned int rate_max;
     125        unsigned int channels_min;
     126        unsigned int channels_max;
     127};
     128
     129struct snd_dummy {
     130        struct snd_card *card;
     131        struct dummy_model *model;
     132        struct snd_pcm *pcm;
     133        struct snd_pcm_hardware pcm_hw;
     134        spinlock_t mixer_lock;
     135        int mixer_volume[MIXER_ADDR_LAST+1][2];
     136        int capture_source[MIXER_ADDR_LAST+1][2];
     137        const struct dummy_timer_ops *timer_ops;
     138};
     139
     140/*
     141 * card models
     142 */
     143
    47144static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)
    48145{
     
    56153        return 0;
    57154}
    58 #define add_playback_constraints emu10k1_playback_constraints
    59 #endif
    60 
    61 #if 0 /* RME9652 emulation */
    62 #define MAX_BUFFER_SIZE         (26 * 64 * 1024)
    63 #define USE_FORMATS             SNDRV_PCM_FMTBIT_S32_LE
    64 #define USE_CHANNELS_MIN        26
    65 #define USE_CHANNELS_MAX        26
    66 #define USE_PERIODS_MIN         2
    67 #define USE_PERIODS_MAX         2
    68 #endif
    69 
    70 #if 0 /* ICE1712 emulation */
    71 #define MAX_BUFFER_SIZE         (256 * 1024)
    72 #define USE_FORMATS             SNDRV_PCM_FMTBIT_S32_LE
    73 #define USE_CHANNELS_MIN        10
    74 #define USE_CHANNELS_MAX        10
    75 #define USE_PERIODS_MIN         1
    76 #define USE_PERIODS_MAX         1024
    77 #endif
    78 
    79 #if 0 /* UDA1341 emulation */
    80 #define MAX_BUFFER_SIZE         (16380)
    81 #define USE_FORMATS             SNDRV_PCM_FMTBIT_S16_LE
    82 #define USE_CHANNELS_MIN        2
    83 #define USE_CHANNELS_MAX        2
    84 #define USE_PERIODS_MIN         2
    85 #define USE_PERIODS_MAX         255
    86 #endif
    87 
    88 #if 0 /* simple AC97 bridge (intel8x0) with 48kHz AC97 only codec */
    89 #define USE_FORMATS             SNDRV_PCM_FMTBIT_S16_LE
    90 #define USE_CHANNELS_MIN        2
    91 #define USE_CHANNELS_MAX        2
    92 #define USE_RATE                SNDRV_PCM_RATE_48000
    93 #define USE_RATE_MIN            48000
    94 #define USE_RATE_MAX            48000
    95 #endif
    96 
    97 #if 0 /* CA0106 */
    98 #define USE_FORMATS             SNDRV_PCM_FMTBIT_S16_LE
    99 #define USE_CHANNELS_MIN        2
    100 #define USE_CHANNELS_MAX        2
    101 #define USE_RATE                (SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_192000)
    102 #define USE_RATE_MIN            48000
    103 #define USE_RATE_MAX            192000
    104 #define MAX_BUFFER_SIZE         ((65536-64)*8)
    105 #define MAX_PERIOD_SIZE         (65536-64)
    106 #define USE_PERIODS_MIN         2
    107 #define USE_PERIODS_MAX         8
    108 #endif
    109 
    110 
    111 /* defaults */
    112 #ifndef MAX_BUFFER_SIZE
    113 #define MAX_BUFFER_SIZE         (64*1024)
    114 #endif
    115 #ifndef MAX_PERIOD_SIZE
    116 #define MAX_PERIOD_SIZE         MAX_BUFFER_SIZE
    117 #endif
    118 #ifndef USE_FORMATS
    119 #define USE_FORMATS             (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
    120 #endif
    121 #ifndef USE_RATE
    122 #define USE_RATE                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000
    123 #define USE_RATE_MIN            5500
    124 #define USE_RATE_MAX            48000
    125 #endif
    126 #ifndef USE_CHANNELS_MIN
    127 #define USE_CHANNELS_MIN        1
    128 #endif
    129 #ifndef USE_CHANNELS_MAX
    130 #define USE_CHANNELS_MAX        2
    131 #endif
    132 #ifndef USE_PERIODS_MIN
    133 #define USE_PERIODS_MIN         1
    134 #endif
    135 #ifndef USE_PERIODS_MAX
    136 #define USE_PERIODS_MAX         1024
    137 #endif
    138 #ifndef add_playback_constraints
    139 #define add_playback_constraints(x) 0
    140 #endif
    141 #ifndef add_capture_constraints
    142 #define add_capture_constraints(x) 0
    143 #endif
    144 
    145 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;      /* Index 0-MAX */
    146 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;       /* ID for this card */
    147 static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
    148 static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
    149 static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};
    150 //static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
    151 
    152 module_param_array(index, int, NULL, 0444);
    153 MODULE_PARM_DESC(index, "Index value for dummy soundcard.");
    154 module_param_array(id, charp, NULL, 0444);
    155 MODULE_PARM_DESC(id, "ID string for dummy soundcard.");
    156 module_param_array(enable, bool, NULL, 0444);
    157 MODULE_PARM_DESC(enable, "Enable this dummy soundcard.");
    158 module_param_array(pcm_devs, int, NULL, 0444);
    159 MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver.");
    160 module_param_array(pcm_substreams, int, NULL, 0444);
    161 MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver.");
    162 module_param_array(midi_devs, int, NULL, 0444);
    163 MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
    164 
    165 static struct platform_device *devices[SNDRV_CARDS];
    166 
    167 #define MIXER_ADDR_MASTER       0
    168 #define MIXER_ADDR_LINE         1
    169 #define MIXER_ADDR_MIC          2
    170 #define MIXER_ADDR_SYNTH        3
    171 #define MIXER_ADDR_CD           4
    172 #define MIXER_ADDR_LAST         4
    173 
    174 struct snd_dummy {
    175         struct snd_card *card;
    176         struct snd_pcm *pcm;
    177         spinlock_t mixer_lock;
    178         int mixer_volume[MIXER_ADDR_LAST+1][2];
    179         int capture_source[MIXER_ADDR_LAST+1][2];
    180 };
    181 
    182 struct snd_dummy_pcm {
    183         struct snd_dummy *dummy;
     155
     156struct dummy_model model_emu10k1 = {
     157        .name = "emu10k1",
     158        .playback_constraints = emu10k1_playback_constraints,
     159        .buffer_bytes_max = 128 * 1024,
     160};
     161
     162struct dummy_model model_rme9652 = {
     163        .name = "rme9652",
     164        .buffer_bytes_max = 26 * 64 * 1024,
     165        .formats = SNDRV_PCM_FMTBIT_S32_LE,
     166        .channels_min = 26,
     167        .channels_max = 26,
     168        .periods_min = 2,
     169        .periods_max = 2,
     170};
     171
     172struct dummy_model model_ice1712 = {
     173        .name = "ice1712",
     174        .buffer_bytes_max = 256 * 1024,
     175        .formats = SNDRV_PCM_FMTBIT_S32_LE,
     176        .channels_min = 10,
     177        .channels_max = 10,
     178        .periods_min = 1,
     179        .periods_max = 1024,
     180};
     181
     182struct dummy_model model_uda1341 = {
     183        .name = "uda1341",
     184        .buffer_bytes_max = 16380,
     185        .formats = SNDRV_PCM_FMTBIT_S16_LE,
     186        .channels_min = 2,
     187        .channels_max = 2,
     188        .periods_min = 2,
     189        .periods_max = 255,
     190};
     191
     192struct dummy_model model_ac97 = {
     193        .name = "ac97",
     194        .formats = SNDRV_PCM_FMTBIT_S16_LE,
     195        .channels_min = 2,
     196        .channels_max = 2,
     197        .rates = SNDRV_PCM_RATE_48000,
     198        .rate_min = 48000,
     199        .rate_max = 48000,
     200};
     201
     202struct dummy_model model_ca0106 = {
     203        .name = "ca0106",
     204        .formats = SNDRV_PCM_FMTBIT_S16_LE,
     205        .buffer_bytes_max = ((65536-64)*8),
     206        .period_bytes_max = (65536-64),
     207        .periods_min = 2,
     208        .periods_max = 8,
     209        .channels_min = 2,
     210        .channels_max = 2,
     211        .rates = SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_192000,
     212        .rate_min = 48000,
     213        .rate_max = 192000,
     214};
     215
     216struct dummy_model *dummy_models[] = {
     217        &model_emu10k1,
     218        &model_rme9652,
     219        &model_ice1712,
     220        &model_uda1341,
     221        &model_ac97,
     222        &model_ca0106,
     223        NULL
     224};
     225
     226/*
     227 * system timer interface
     228 */
     229
     230struct dummy_systimer_pcm {
    184231        spinlock_t lock;
    185232        struct timer_list timer;
    186         unsigned int pcm_buffer_size;
    187         unsigned int pcm_period_size;
    188         unsigned int pcm_bps;           /* bytes per second */
    189         unsigned int pcm_hz;            /* HZ */
    190         unsigned int pcm_irq_pos;       /* IRQ position */
    191         unsigned int pcm_buf_pos;       /* position in buffer */
     233        unsigned long base_time;
     234        unsigned int frac_pos;  /* fractional sample position (based HZ) */
     235        unsigned int frac_period_rest;
     236        unsigned int frac_buffer_size;  /* buffer_size * HZ */
     237        unsigned int frac_period_size;  /* period_size * HZ */
     238        unsigned int rate;
     239        int elapsed;
    192240        struct snd_pcm_substream *substream;
    193241};
    194242
    195 
    196 static inline void snd_card_dummy_pcm_timer_start(struct snd_dummy_pcm *dpcm)
    197 {
    198         dpcm->timer.expires = 1 + jiffies;
     243static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm)
     244{
     245        dpcm->timer.expires = jiffies +
     246                (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate;
    199247        add_timer(&dpcm->timer);
    200248}
    201249
    202 static inline void snd_card_dummy_pcm_timer_stop(struct snd_dummy_pcm *dpcm)
    203 {
     250static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm)
     251{
     252        unsigned long delta;
     253
     254        delta = jiffies - dpcm->base_time;
     255        if (!delta)
     256                return;
     257        dpcm->base_time += delta;
     258        delta *= dpcm->rate;
     259        dpcm->frac_pos += delta;
     260        while (dpcm->frac_pos >= dpcm->frac_buffer_size)
     261                dpcm->frac_pos -= dpcm->frac_buffer_size;
     262        while (dpcm->frac_period_rest <= delta) {
     263                dpcm->elapsed++;
     264                dpcm->frac_period_rest += dpcm->frac_period_size;
     265        }
     266        dpcm->frac_period_rest -= delta;
     267}
     268
     269static int dummy_systimer_start(struct snd_pcm_substream *substream)
     270{
     271        struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;
     272        spin_lock(&dpcm->lock);
     273        dpcm->base_time = jiffies;
     274        dummy_systimer_rearm(dpcm);
     275        spin_unlock(&dpcm->lock);
     276        return 0;
     277}
     278
     279static int dummy_systimer_stop(struct snd_pcm_substream *substream)
     280{
     281        struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;
     282        spin_lock(&dpcm->lock);
    204283        del_timer(&dpcm->timer);
    205 }
    206 
    207 static int snd_card_dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
     284        spin_unlock(&dpcm->lock);
     285        return 0;
     286}
     287
     288static int dummy_systimer_prepare(struct snd_pcm_substream *substream)
    208289{
    209290        struct snd_pcm_runtime *runtime = substream->runtime;
    210         struct snd_dummy_pcm *dpcm = runtime->private_data;
    211         int err = 0;
     291        struct dummy_systimer_pcm *dpcm = runtime->private_data;
     292
     293        dpcm->frac_pos = 0;
     294        dpcm->rate = runtime->rate;
     295        dpcm->frac_buffer_size = runtime->buffer_size * HZ;
     296        dpcm->frac_period_size = runtime->period_size * HZ;
     297        dpcm->frac_period_rest = dpcm->frac_period_size;
     298        dpcm->elapsed = 0;
     299
     300        return 0;
     301}
     302
     303static void dummy_systimer_callback(unsigned long data)
     304{
     305        struct dummy_systimer_pcm *dpcm = (struct dummy_systimer_pcm *)data;
     306        unsigned long flags;
     307        int elapsed = 0;
     308       
     309        spin_lock_irqsave(&dpcm->lock, flags);
     310        dummy_systimer_update(dpcm);
     311        dummy_systimer_rearm(dpcm);
     312        elapsed = dpcm->elapsed;
     313        dpcm->elapsed = 0;
     314        spin_unlock_irqrestore(&dpcm->lock, flags);
     315        if (elapsed)
     316                snd_pcm_period_elapsed(dpcm->substream);
     317}
     318
     319static snd_pcm_uframes_t
     320dummy_systimer_pointer(struct snd_pcm_substream *substream)
     321{
     322        struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;
     323        snd_pcm_uframes_t pos;
    212324
    213325        spin_lock(&dpcm->lock);
     326        dummy_systimer_update(dpcm);
     327        pos = dpcm->frac_pos / HZ;
     328        spin_unlock(&dpcm->lock);
     329        return pos;
     330}
     331
     332static int dummy_systimer_create(struct snd_pcm_substream *substream)
     333{
     334        struct dummy_systimer_pcm *dpcm;
     335
     336        dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
     337        if (!dpcm)
     338                return -ENOMEM;
     339        substream->runtime->private_data = dpcm;
     340        init_timer(&dpcm->timer);
     341        dpcm->timer.data = (unsigned long) dpcm;
     342        dpcm->timer.function = dummy_systimer_callback;
     343        spin_lock_init(&dpcm->lock);
     344        dpcm->substream = substream;
     345        return 0;
     346}
     347
     348static void dummy_systimer_free(struct snd_pcm_substream *substream)
     349{
     350        kfree(substream->runtime->private_data);
     351}
     352
     353static struct dummy_timer_ops dummy_systimer_ops = {
     354        .create =       dummy_systimer_create,
     355        .free =         dummy_systimer_free,
     356        .prepare =      dummy_systimer_prepare,
     357        .start =        dummy_systimer_start,
     358        .stop =         dummy_systimer_stop,
     359        .pointer =      dummy_systimer_pointer,
     360};
     361
     362#ifdef CONFIG_HIGH_RES_TIMERS
     363/*
     364 * hrtimer interface
     365 */
     366
     367struct dummy_hrtimer_pcm {
     368        ktime_t base_time;
     369        ktime_t period_time;
     370        atomic_t running;
     371        struct hrtimer timer;
     372        struct tasklet_struct tasklet;
     373        struct snd_pcm_substream *substream;
     374};
     375
     376static void dummy_hrtimer_pcm_elapsed(unsigned long priv)
     377{
     378        struct dummy_hrtimer_pcm *dpcm = (struct dummy_hrtimer_pcm *)priv;
     379        if (atomic_read(&dpcm->running))
     380                snd_pcm_period_elapsed(dpcm->substream);
     381}
     382
     383static enum hrtimer_restart dummy_hrtimer_callback(struct hrtimer *timer)
     384{
     385        struct dummy_hrtimer_pcm *dpcm;
     386
     387        dpcm = container_of(timer, struct dummy_hrtimer_pcm, timer);
     388        if (!atomic_read(&dpcm->running))
     389                return HRTIMER_NORESTART;
     390        tasklet_schedule(&dpcm->tasklet);
     391        hrtimer_forward_now(timer, dpcm->period_time);
     392        return HRTIMER_RESTART;
     393}
     394
     395static int dummy_hrtimer_start(struct snd_pcm_substream *substream)
     396{
     397        struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;
     398
     399        dpcm->base_time = hrtimer_cb_get_time(&dpcm->timer);
     400        hrtimer_start(&dpcm->timer, dpcm->period_time, HRTIMER_MODE_REL);
     401        atomic_set(&dpcm->running, 1);
     402        return 0;
     403}
     404
     405static int dummy_hrtimer_stop(struct snd_pcm_substream *substream)
     406{
     407        struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;
     408
     409        atomic_set(&dpcm->running, 0);
     410        hrtimer_cancel(&dpcm->timer);
     411        return 0;
     412}
     413
     414static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm)
     415{
     416        tasklet_kill(&dpcm->tasklet);
     417}
     418
     419static snd_pcm_uframes_t
     420dummy_hrtimer_pointer(struct snd_pcm_substream *substream)
     421{
     422        struct snd_pcm_runtime *runtime = substream->runtime;
     423        struct dummy_hrtimer_pcm *dpcm = runtime->private_data;
     424        u64 delta;
     425        u32 pos;
     426
     427        delta = ktime_us_delta(hrtimer_cb_get_time(&dpcm->timer),
     428                               dpcm->base_time);
     429        delta = div_u64(delta * runtime->rate + 999999, 1000000);
     430        div_u64_rem(delta, runtime->buffer_size, &pos);
     431        return pos;
     432}
     433
     434static int dummy_hrtimer_prepare(struct snd_pcm_substream *substream)
     435{
     436        struct snd_pcm_runtime *runtime = substream->runtime;
     437        struct dummy_hrtimer_pcm *dpcm = runtime->private_data;
     438        unsigned int period, rate;
     439        long sec;
     440        unsigned long nsecs;
     441
     442        dummy_hrtimer_sync(dpcm);
     443        period = runtime->period_size;
     444        rate = runtime->rate;
     445        sec = period / rate;
     446        period %= rate;
     447        nsecs = div_u64((u64)period * 1000000000UL + rate - 1, rate);
     448        dpcm->period_time = ktime_set(sec, nsecs);
     449
     450        return 0;
     451}
     452
     453static int dummy_hrtimer_create(struct snd_pcm_substream *substream)
     454{
     455        struct dummy_hrtimer_pcm *dpcm;
     456
     457        dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
     458        if (!dpcm)
     459                return -ENOMEM;
     460        substream->runtime->private_data = dpcm;
     461        hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
     462        dpcm->timer.function = dummy_hrtimer_callback;
     463        dpcm->substream = substream;
     464        atomic_set(&dpcm->running, 0);
     465        tasklet_init(&dpcm->tasklet, dummy_hrtimer_pcm_elapsed,
     466                     (unsigned long)dpcm);
     467        return 0;
     468}
     469
     470static void dummy_hrtimer_free(struct snd_pcm_substream *substream)
     471{
     472        struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;
     473        dummy_hrtimer_sync(dpcm);
     474        kfree(dpcm);
     475}
     476
     477static struct dummy_timer_ops dummy_hrtimer_ops = {
     478        .create =       dummy_hrtimer_create,
     479        .free =         dummy_hrtimer_free,
     480        .prepare =      dummy_hrtimer_prepare,
     481        .start =        dummy_hrtimer_start,
     482        .stop =         dummy_hrtimer_stop,
     483        .pointer =      dummy_hrtimer_pointer,
     484};
     485
     486#endif /* CONFIG_HIGH_RES_TIMERS */
     487
     488/*
     489 * PCM interface
     490 */
     491
     492static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
     493{
     494        struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
     495
    214496        switch (cmd) {
    215497        case SNDRV_PCM_TRIGGER_START:
    216498        case SNDRV_PCM_TRIGGER_RESUME:
    217                 snd_card_dummy_pcm_timer_start(dpcm);
    218                 break;
     499                return dummy->timer_ops->start(substream);
    219500        case SNDRV_PCM_TRIGGER_STOP:
    220501        case SNDRV_PCM_TRIGGER_SUSPEND:
    221                 snd_card_dummy_pcm_timer_stop(dpcm);
    222                 break;
    223         default:
    224                 err = -EINVAL;
    225                 break;
    226         }
    227         spin_unlock(&dpcm->lock);
    228         return 0;
    229 }
    230 
    231 static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
    232 {
    233         struct snd_pcm_runtime *runtime = substream->runtime;
    234         struct snd_dummy_pcm *dpcm = runtime->private_data;
    235         int bps;
    236 
    237         bps = snd_pcm_format_width(runtime->format) * runtime->rate *
    238                 runtime->channels / 8;
    239 
    240         if (bps <= 0)
    241                 return -EINVAL;
    242 
    243         dpcm->pcm_bps = bps;
    244         dpcm->pcm_hz = HZ;
    245         dpcm->pcm_buffer_size = snd_pcm_lib_buffer_bytes(substream);
    246         dpcm->pcm_period_size = snd_pcm_lib_period_bytes(substream);
    247         dpcm->pcm_irq_pos = 0;
    248         dpcm->pcm_buf_pos = 0;
    249 
    250         snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
    251                         bytes_to_samples(runtime, runtime->dma_bytes));
    252 
    253         return 0;
    254 }
    255 
    256 static void snd_card_dummy_pcm_timer_function(unsigned long data)
    257 {
    258         struct snd_dummy_pcm *dpcm = (struct snd_dummy_pcm *)data;
    259         unsigned long flags;
    260        
    261         spin_lock_irqsave(&dpcm->lock, flags);
    262         dpcm->timer.expires = 1 + jiffies;
    263         add_timer(&dpcm->timer);
    264         dpcm->pcm_irq_pos += dpcm->pcm_bps;
    265         dpcm->pcm_buf_pos += dpcm->pcm_bps;
    266         dpcm->pcm_buf_pos %= dpcm->pcm_buffer_size * dpcm->pcm_hz;
    267         if (dpcm->pcm_irq_pos >= dpcm->pcm_period_size * dpcm->pcm_hz) {
    268                 dpcm->pcm_irq_pos %= dpcm->pcm_period_size * dpcm->pcm_hz;
    269                 spin_unlock_irqrestore(&dpcm->lock, flags);
    270                 snd_pcm_period_elapsed(dpcm->substream);
    271         } else
    272                 spin_unlock_irqrestore(&dpcm->lock, flags);
    273 }
    274 
    275 static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *substream)
    276 {
    277         struct snd_pcm_runtime *runtime = substream->runtime;
    278         struct snd_dummy_pcm *dpcm = runtime->private_data;
    279 
    280         return bytes_to_frames(runtime, dpcm->pcm_buf_pos / dpcm->pcm_hz);
    281 }
    282 
    283 static struct snd_pcm_hardware snd_card_dummy_playback =
    284 {
    285         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
    286                                  SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
     502                return dummy->timer_ops->stop(substream);
     503        }
     504        return -EINVAL;
     505}
     506
     507static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
     508{
     509        struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
     510
     511        return dummy->timer_ops->prepare(substream);
     512}
     513
     514static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)
     515{
     516        struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
     517
     518        return dummy->timer_ops->pointer(substream);
     519}
     520
     521static struct snd_pcm_hardware dummy_pcm_hardware = {
     522        .info =                 (SNDRV_PCM_INFO_MMAP |
     523                                 SNDRV_PCM_INFO_INTERLEAVED |
     524                                 SNDRV_PCM_INFO_RESUME |
     525                                 SNDRV_PCM_INFO_MMAP_VALID),
    287526        .formats =              USE_FORMATS,
    288527        .rates =                USE_RATE,
     
    292531        .channels_max =         USE_CHANNELS_MAX,
    293532        .buffer_bytes_max =     MAX_BUFFER_SIZE,
    294         .period_bytes_min =     64,
     533        .period_bytes_min =     MIN_PERIOD_SIZE,
    295534        .period_bytes_max =     MAX_PERIOD_SIZE,
    296535        .periods_min =          USE_PERIODS_MIN,
     
    299538};
    300539
    301 static struct snd_pcm_hardware snd_card_dummy_capture =
    302 {
    303         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
    304                                  SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
    305         .formats =              USE_FORMATS,
    306         .rates =                USE_RATE,
    307         .rate_min =             USE_RATE_MIN,
    308         .rate_max =             USE_RATE_MAX,
    309         .channels_min =         USE_CHANNELS_MIN,
    310         .channels_max =         USE_CHANNELS_MAX,
    311         .buffer_bytes_max =     MAX_BUFFER_SIZE,
    312         .period_bytes_min =     64,
    313         .period_bytes_max =     MAX_PERIOD_SIZE,
    314         .periods_min =          USE_PERIODS_MIN,
    315         .periods_max =          USE_PERIODS_MAX,
    316         .fifo_size =            0,
    317 };
    318 
    319 static void snd_card_dummy_runtime_free(struct snd_pcm_runtime *runtime)
    320 {
    321         kfree(runtime->private_data);
    322 }
    323 
    324 static int snd_card_dummy_hw_params(struct snd_pcm_substream *substream,
    325                                     struct snd_pcm_hw_params *hw_params)
    326 {
    327         return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
    328 }
    329 
    330 static int snd_card_dummy_hw_free(struct snd_pcm_substream *substream)
    331 {
     540static int dummy_pcm_hw_params(struct snd_pcm_substream *substream,
     541                               struct snd_pcm_hw_params *hw_params)
     542{
     543        if (fake_buffer) {
     544                /* runtime->dma_bytes has to be set manually to allow mmap */
     545                substream->runtime->dma_bytes = params_buffer_bytes(hw_params);
     546                return 0;
     547        }
     548        return snd_pcm_lib_malloc_pages(substream,
     549                                        params_buffer_bytes(hw_params));
     550}
     551
     552static int dummy_pcm_hw_free(struct snd_pcm_substream *substream)
     553{
     554        if (fake_buffer)
     555                return 0;
    332556        return snd_pcm_lib_free_pages(substream);
    333557}
    334558
    335 static struct snd_dummy_pcm *new_pcm_stream(struct snd_pcm_substream *substream)
    336 {
    337         struct snd_dummy_pcm *dpcm;
    338 
    339         dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
    340         if (! dpcm)
    341                 return dpcm;
    342         init_timer(&dpcm->timer);
    343         dpcm->timer.data = (unsigned long) dpcm;
    344         dpcm->timer.function = snd_card_dummy_pcm_timer_function;
    345         spin_lock_init(&dpcm->lock);
    346         dpcm->substream = substream;
    347         return dpcm;
    348 }
    349 
    350 static int snd_card_dummy_playback_open(struct snd_pcm_substream *substream)
    351 {
     559static int dummy_pcm_open(struct snd_pcm_substream *substream)
     560{
     561        struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
     562        struct dummy_model *model = dummy->model;
    352563        struct snd_pcm_runtime *runtime = substream->runtime;
    353         struct snd_dummy_pcm *dpcm;
    354564        int err;
    355565
    356         if ((dpcm = new_pcm_stream(substream)) == NULL)
    357                 return -ENOMEM;
    358         runtime->private_data = dpcm;
    359         /* makes the infrastructure responsible for freeing dpcm */
    360         runtime->private_free = snd_card_dummy_runtime_free;
    361         runtime->hw = snd_card_dummy_playback;
     566        dummy->timer_ops = &dummy_systimer_ops;
     567#ifdef CONFIG_HIGH_RES_TIMERS
     568        if (hrtimer)
     569                dummy->timer_ops = &dummy_hrtimer_ops;
     570#endif
     571
     572        err = dummy->timer_ops->create(substream);
     573        if (err < 0)
     574                return err;
     575
     576        runtime->hw = dummy->pcm_hw;
    362577        if (substream->pcm->device & 1) {
    363578                runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
     
    365580        }
    366581        if (substream->pcm->device & 2)
    367                 runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
    368         err = add_playback_constraints(runtime);
    369         if (err < 0)
     582                runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |
     583                                      SNDRV_PCM_INFO_MMAP_VALID);
     584
     585        if (model == NULL)
     586                return 0;
     587
     588        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
     589                if (model->playback_constraints)
     590                        err = model->playback_constraints(substream->runtime);
     591        } else {
     592                if (model->capture_constraints)
     593                        err = model->capture_constraints(substream->runtime);
     594        }
     595        if (err < 0) {
     596                dummy->timer_ops->free(substream);
    370597                return err;
    371 
    372         return 0;
    373 }
    374 
    375 static int snd_card_dummy_capture_open(struct snd_pcm_substream *substream)
    376 {
    377         struct snd_pcm_runtime *runtime = substream->runtime;
    378         struct snd_dummy_pcm *dpcm;
    379         int err;
    380 
    381         if ((dpcm = new_pcm_stream(substream)) == NULL)
    382                 return -ENOMEM;
    383         runtime->private_data = dpcm;
    384         /* makes the infrastructure responsible for freeing dpcm */
    385         runtime->private_free = snd_card_dummy_runtime_free;
    386         runtime->hw = snd_card_dummy_capture;
    387         if (substream->pcm->device == 1) {
    388                 runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
    389                 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
    390         }
    391         if (substream->pcm->device & 2)
    392                 runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
    393         err = add_capture_constraints(runtime);
    394         if (err < 0)
    395                 return err;
    396 
    397         return 0;
    398 }
    399 
    400 static int snd_card_dummy_playback_close(struct snd_pcm_substream *substream)
    401 {
    402         return 0;
    403 }
    404 
    405 static int snd_card_dummy_capture_close(struct snd_pcm_substream *substream)
    406 {
    407         return 0;
    408 }
    409 
    410 static struct snd_pcm_ops snd_card_dummy_playback_ops = {
    411         .open =                 snd_card_dummy_playback_open,
    412         .close =                snd_card_dummy_playback_close,
    413         .ioctl =                snd_pcm_lib_ioctl,
    414         .hw_params =            snd_card_dummy_hw_params,
    415         .hw_free =              snd_card_dummy_hw_free,
    416         .prepare =              snd_card_dummy_pcm_prepare,
    417         .trigger =              snd_card_dummy_pcm_trigger,
    418         .pointer =              snd_card_dummy_pcm_pointer,
    419 };
    420 
    421 static struct snd_pcm_ops snd_card_dummy_capture_ops = {
    422         .open =                 snd_card_dummy_capture_open,
    423         .close =                snd_card_dummy_capture_close,
    424         .ioctl =                snd_pcm_lib_ioctl,
    425         .hw_params =            snd_card_dummy_hw_params,
    426         .hw_free =              snd_card_dummy_hw_free,
    427         .prepare =              snd_card_dummy_pcm_prepare,
    428         .trigger =              snd_card_dummy_pcm_trigger,
    429         .pointer =              snd_card_dummy_pcm_pointer,
     598        }
     599        return 0;
     600}
     601
     602static int dummy_pcm_close(struct snd_pcm_substream *substream)
     603{
     604        struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
     605        dummy->timer_ops->free(substream);
     606        return 0;
     607}
     608
     609/*
     610 * dummy buffer handling
     611 */
     612
     613static void *dummy_page[2];
     614
     615static void free_fake_buffer(void)
     616{
     617        if (fake_buffer) {
     618                int i;
     619                for (i = 0; i < 2; i++)
     620                        if (dummy_page[i]) {
     621                                free_page((unsigned long)dummy_page[i]);
     622                                dummy_page[i] = NULL;
     623                        }
     624        }
     625}
     626
     627static int alloc_fake_buffer(void)
     628{
     629        int i;
     630
     631        if (!fake_buffer)
     632                return 0;
     633        for (i = 0; i < 2; i++) {
     634                dummy_page[i] = (void *)get_zeroed_page(GFP_KERNEL);
     635                if (!dummy_page[i]) {
     636                        free_fake_buffer();
     637                        return -ENOMEM;
     638                }
     639        }
     640        return 0;
     641}
     642
     643static int dummy_pcm_copy(struct snd_pcm_substream *substream,
     644                          int channel, snd_pcm_uframes_t pos,
     645                          void __user *dst, snd_pcm_uframes_t count)
     646{
     647        return 0; /* do nothing */
     648}
     649
     650static int dummy_pcm_silence(struct snd_pcm_substream *substream,
     651                             int channel, snd_pcm_uframes_t pos,
     652                             snd_pcm_uframes_t count)
     653{
     654        return 0; /* do nothing */
     655}
     656
     657static struct page *dummy_pcm_page(struct snd_pcm_substream *substream,
     658                                   unsigned long offset)
     659{
     660        return virt_to_page(dummy_page[substream->stream]); /* the same page */
     661}
     662
     663static struct snd_pcm_ops dummy_pcm_ops = {
     664        .open =         dummy_pcm_open,
     665        .close =        dummy_pcm_close,
     666        .ioctl =        snd_pcm_lib_ioctl,
     667        .hw_params =    dummy_pcm_hw_params,
     668        .hw_free =      dummy_pcm_hw_free,
     669        .prepare =      dummy_pcm_prepare,
     670        .trigger =      dummy_pcm_trigger,
     671        .pointer =      dummy_pcm_pointer,
     672};
     673
     674static struct snd_pcm_ops dummy_pcm_ops_no_buf = {
     675        .open =         dummy_pcm_open,
     676        .close =        dummy_pcm_close,
     677        .ioctl =        snd_pcm_lib_ioctl,
     678        .hw_params =    dummy_pcm_hw_params,
     679        .hw_free =      dummy_pcm_hw_free,
     680        .prepare =      dummy_pcm_prepare,
     681        .trigger =      dummy_pcm_trigger,
     682        .pointer =      dummy_pcm_pointer,
     683        .copy =         dummy_pcm_copy,
     684        .silence =      dummy_pcm_silence,
     685        .page =         dummy_pcm_page,
    430686};
    431687
     
    434690{
    435691        struct snd_pcm *pcm;
     692        struct snd_pcm_ops *ops;
    436693        int err;
    437694
     
    441698                return err;
    442699        dummy->pcm = pcm;
    443         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops);
    444         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_dummy_capture_ops);
     700        if (fake_buffer)
     701                ops = &dummy_pcm_ops_no_buf;
     702        else
     703                ops = &dummy_pcm_ops;
     704        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, ops);
     705        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, ops);
    445706        pcm->private_data = dummy;
    446707        pcm->info_flags = 0;
    447708        strcpy(pcm->name, "Dummy PCM");
    448         snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
    449                                               snd_dma_continuous_data(GFP_KERNEL),
    450                                               0, 64*1024);
    451         return 0;
    452 }
     709        if (!fake_buffer) {
     710                snd_pcm_lib_preallocate_pages_for_all(pcm,
     711                        SNDRV_DMA_TYPE_CONTINUOUS,
     712                        snd_dma_continuous_data(GFP_KERNEL),
     713                        0, 64*1024);
     714        }
     715        return 0;
     716}
     717
     718/*
     719 * mixer interface
     720 */
    453721
    454722#define DUMMY_VOLUME(xname, xindex, addr) \
     
    569837        int err;
    570838
    571         if (snd_BUG_ON(!dummy))
    572                 return -EINVAL;
    573839        spin_lock_init(&dummy->mixer_lock);
    574840        strcpy(card->mixername, "Dummy Mixer");
     
    582848}
    583849
     850#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_PROC_FS)
     851/*
     852 * proc interface
     853 */
     854static void print_formats(struct snd_dummy *dummy,
     855                          struct snd_info_buffer *buffer)
     856{
     857        int i;
     858
     859        for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) {
     860                if (dummy->pcm_hw.formats & (1ULL << i))
     861                        snd_iprintf(buffer, " %s", snd_pcm_format_name(i));
     862        }
     863}
     864
     865static void print_rates(struct snd_dummy *dummy,
     866                        struct snd_info_buffer *buffer)
     867{
     868        static int rates[] = {
     869                5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
     870                64000, 88200, 96000, 176400, 192000,
     871        };
     872        int i;
     873
     874        if (dummy->pcm_hw.rates & SNDRV_PCM_RATE_CONTINUOUS)
     875                snd_iprintf(buffer, " continuous");
     876        if (dummy->pcm_hw.rates & SNDRV_PCM_RATE_KNOT)
     877                snd_iprintf(buffer, " knot");
     878        for (i = 0; i < ARRAY_SIZE(rates); i++)
     879                if (dummy->pcm_hw.rates & (1 << i))
     880                        snd_iprintf(buffer, " %d", rates[i]);
     881}
     882
     883#define get_dummy_int_ptr(dummy, ofs) \
     884        (unsigned int *)((char *)&((dummy)->pcm_hw) + (ofs))
     885#define get_dummy_ll_ptr(dummy, ofs) \
     886        (unsigned long long *)((char *)&((dummy)->pcm_hw) + (ofs))
     887
     888struct dummy_hw_field {
     889        const char *name;
     890        const char *format;
     891        unsigned int offset;
     892        unsigned int size;
     893};
     894#define FIELD_ENTRY(item, fmt) {                   \
     895        .name = #item,                             \
     896        .format = fmt,                             \
     897        .offset = offsetof(struct snd_pcm_hardware, item), \
     898        .size = sizeof(dummy_pcm_hardware.item) }
     899
     900static struct dummy_hw_field fields[] = {
     901        FIELD_ENTRY(formats, "%#llx"),
     902        FIELD_ENTRY(rates, "%#x"),
     903        FIELD_ENTRY(rate_min, "%d"),
     904        FIELD_ENTRY(rate_max, "%d"),
     905        FIELD_ENTRY(channels_min, "%d"),
     906        FIELD_ENTRY(channels_max, "%d"),
     907        FIELD_ENTRY(buffer_bytes_max, "%ld"),
     908        FIELD_ENTRY(period_bytes_min, "%ld"),
     909        FIELD_ENTRY(period_bytes_max, "%ld"),
     910        FIELD_ENTRY(periods_min, "%d"),
     911        FIELD_ENTRY(periods_max, "%d"),
     912};
     913
     914static void dummy_proc_read(struct snd_info_entry *entry,
     915                            struct snd_info_buffer *buffer)
     916{
     917        struct snd_dummy *dummy = entry->private_data;
     918        int i;
     919
     920        for (i = 0; i < ARRAY_SIZE(fields); i++) {
     921                snd_iprintf(buffer, "%s ", fields[i].name);
     922                if (fields[i].size == sizeof(int))
     923                        snd_iprintf(buffer, fields[i].format,
     924                                *get_dummy_int_ptr(dummy, fields[i].offset));
     925                else
     926                        snd_iprintf(buffer, fields[i].format,
     927                                *get_dummy_ll_ptr(dummy, fields[i].offset));
     928                if (!strcmp(fields[i].name, "formats"))
     929                        print_formats(dummy, buffer);
     930                else if (!strcmp(fields[i].name, "rates"))
     931                        print_rates(dummy, buffer);
     932                snd_iprintf(buffer, "\n");
     933        }
     934}
     935
     936static void dummy_proc_write(struct snd_info_entry *entry,
     937                             struct snd_info_buffer *buffer)
     938{
     939        struct snd_dummy *dummy = entry->private_data;
     940        char line[64];
     941
     942        while (!snd_info_get_line(buffer, line, sizeof(line))) {
     943                char item[20];
     944                const char *ptr;
     945                unsigned long long val;
     946                int i;
     947
     948                ptr = snd_info_get_str(item, line, sizeof(item));
     949                for (i = 0; i < ARRAY_SIZE(fields); i++) {
     950                        if (!strcmp(item, fields[i].name))
     951                                break;
     952                }
     953                if (i >= ARRAY_SIZE(fields))
     954                        continue;
     955                snd_info_get_str(item, ptr, sizeof(item));
     956                if (strict_strtoull(item, 0, &val))
     957                        continue;
     958                if (fields[i].size == sizeof(int))
     959                        *get_dummy_int_ptr(dummy, fields[i].offset) = val;
     960                else
     961                        *get_dummy_ll_ptr(dummy, fields[i].offset) = val;
     962        }
     963}
     964
     965static void __devinit dummy_proc_init(struct snd_dummy *chip)
     966{
     967        struct snd_info_entry *entry;
     968
     969        if (!snd_card_proc_new(chip->card, "dummy_pcm", &entry)) {
     970                snd_info_set_text_ops(entry, chip, dummy_proc_read);
     971                entry->c.text.write = dummy_proc_write;
     972                entry->mode |= S_IWUSR;
     973                entry->private_data = chip;
     974        }
     975}
     976#else
     977#define dummy_proc_init(x)
     978#endif /* CONFIG_SND_DEBUG && CONFIG_PROC_FS */
     979
    584980static int __devinit snd_dummy_probe(struct platform_device *devptr)
    585981{
    586982        struct snd_card *card;
    587983        struct snd_dummy *dummy;
     984        struct dummy_model *m = NULL, **mdl;
    588985        int idx, err;
    589986        int dev = devptr->id;
     
    595992        dummy = card->private_data;
    596993        dummy->card = card;
     994        for (mdl = dummy_models; *mdl && model[dev]; mdl++) {
     995                if (strcmp(model[dev], (*mdl)->name) == 0) {
     996                        printk(KERN_INFO
     997                                "snd-dummy: Using model '%s' for card %i\n",
     998                                (*mdl)->name, card->number);
     999                        m = dummy->model = *mdl;
     1000                        break;
     1001                }
     1002        }
    5971003        for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) {
    5981004                if (pcm_substreams[dev] < 1)
     
    6041010                        goto __nodev;
    6051011        }
     1012
     1013        dummy->pcm_hw = dummy_pcm_hardware;
     1014        if (m) {
     1015                if (m->formats)
     1016                        dummy->pcm_hw.formats = m->formats;
     1017                if (m->buffer_bytes_max)
     1018                        dummy->pcm_hw.buffer_bytes_max = m->buffer_bytes_max;
     1019                if (m->period_bytes_min)
     1020                        dummy->pcm_hw.period_bytes_min = m->period_bytes_min;
     1021                if (m->period_bytes_max)
     1022                        dummy->pcm_hw.period_bytes_max = m->period_bytes_max;
     1023                if (m->periods_min)
     1024                        dummy->pcm_hw.periods_min = m->periods_min;
     1025                if (m->periods_max)
     1026                        dummy->pcm_hw.periods_max = m->periods_max;
     1027                if (m->rates)
     1028                        dummy->pcm_hw.rates = m->rates;
     1029                if (m->rate_min)
     1030                        dummy->pcm_hw.rate_min = m->rate_min;
     1031                if (m->rate_max)
     1032                        dummy->pcm_hw.rate_max = m->rate_max;
     1033                if (m->channels_min)
     1034                        dummy->pcm_hw.channels_min = m->channels_min;
     1035                if (m->channels_max)
     1036                        dummy->pcm_hw.channels_max = m->channels_max;
     1037        }
     1038
    6061039        err = snd_card_dummy_new_mixer(dummy);
    6071040        if (err < 0)
     
    6101043        strcpy(card->shortname, "Dummy");
    6111044        sprintf(card->longname, "Dummy %i", dev + 1);
     1045
     1046        dummy_proc_init(dummy);
    6121047
    6131048        snd_card_set_dev(card, &devptr->dev);
     
    6711106                platform_device_unregister(devices[i]);
    6721107        platform_driver_unregister(&snd_dummy_driver);
     1108        free_fake_buffer();
    6731109}
    6741110
     
    6801116        if (err < 0)
    6811117                return err;
     1118
     1119        err = alloc_fake_buffer();
     1120        if (err < 0) {
     1121                platform_driver_unregister(&snd_dummy_driver);
     1122                return err;
     1123        }
    6821124
    6831125        cards = 0;
Note: See TracChangeset for help on using the changeset viewer.