Changeset fb6c98f in mainline for uspace/drv/audio/sb16/dsp.c


Ignore:
Timestamp:
2012-08-20T14:03:19Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6f57933
Parents:
018ab50
Message:

sb16: Improve state management and use it to reject invalid requests.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/audio/sb16/dsp.c

    r018ab50 rfb6c98f  
    6262#define AUTO_DMA_MODE
    6363
     64static inline const char * dsp_state_to_str(dsp_state_t state)
     65{
     66        static const char* state_names[] = {
     67                [DSP_PLAYBACK_ACTIVE_EVENTS] = "PLAYBACK w/ EVENTS",
     68                [DSP_CAPTURE_ACTIVE_EVENTS] = "CAPTURE w/o ACTIVE",
     69                [DSP_PLAYBACK_NOEVENTS] = "PLAYBACK w/. EVENTS",
     70                [DSP_CAPTURE_NOEVENTS] = "CAPTURE w/o EVENTS",
     71                [DSP_STOPPED] = "STOPPED",
     72                [DSP_READY] = "READY",
     73                [DSP_NO_BUFFER] = "NO BUFFER",
     74        };
     75        if (state < (sizeof(state_names) / sizeof(state_names[0])))
     76                return state_names[state];
     77        return "UNKNOWN";
     78}
     79
     80
     81static inline void sb_dsp_change_state(sb_dsp_t *dsp, dsp_state_t state)
     82{
     83        assert(dsp);
     84        ddf_log_verbose("Changing state from %s to %s",
     85            dsp_state_to_str(dsp->state), dsp_state_to_str(state));
     86        dsp->state = state;
     87}
     88
    6489static inline int sb_dsp_read(sb_dsp_t *dsp, uint8_t *data)
    6590{
     
    162187}
    163188
    164 static inline void sb_clear_buffer(sb_dsp_t *dsp)
    165 {
    166         assert(dsp);
    167         dmamem_unmap_anonymous(dsp->buffer.data);
    168         dsp->buffer.data = NULL;
    169         dsp->buffer.size = 0;
    170 }
    171 
    172189static inline size_t sample_count(pcm_sample_format_t format, size_t byte_count)
    173190{
     
    185202        dsp->event_exchange = NULL;
    186203        dsp->sb_dev = dev;
    187         dsp->status = DSP_STOPPED;
    188         dsp->ignore_interrupts = false;
     204        dsp->state = DSP_NO_BUFFER;
    189205        sb_dsp_reset(dsp);
    190206        /* "DSP takes about 100 microseconds to initialize itself" */
     
    213229        assert(dsp);
    214230
    215 #ifndef AUTO_DMA_MODE
    216         if (dsp->status == DSP_PLAYBACK) {
    217                 sb_dsp_start_active(dsp, SINGLE_DMA_16B_DA);
    218         }
    219 
    220         if (dsp->status == DSP_CAPTURE) {
    221                 sb_dsp_start_active(dsp, SINGLE_DMA_16B_AD);
    222         }
    223 #endif
    224 
    225         if (dsp->ignore_interrupts)
    226                 return;
    227 
    228231        dsp->active.frame_count +=
    229232            dsp->active.samples / ((dsp->active.mode & DSP_MODE_STEREO) ? 2 : 1);
    230233
    231         if (dsp->event_exchange) {
    232                 switch (dsp->status) {
    233                 case DSP_PLAYBACK:
    234                         async_msg_1(dsp->event_exchange,
    235                             PCM_EVENT_FRAMES_PLAYED, dsp->active.frame_count);
    236                         break;
    237                 case DSP_CAPTURE:
    238                         async_msg_1(dsp->event_exchange,
    239                             PCM_EVENT_FRAMES_CAPTURED, dsp->active.frame_count);
    240                         break;
    241                 default:
    242                 case DSP_STOPPED:
    243                         ddf_log_warning("Interrupt while DSP stopped and "
    244                             "event exchange present. Terminating exchange");
    245                         async_exchange_end(dsp->event_exchange);
    246                         dsp->event_exchange = NULL;
    247                 }
    248         } else {
    249                 ddf_log_warning("Interrupt with no event consumer.");
     234        switch (dsp->state)
     235        {
     236        case DSP_PLAYBACK_ACTIVE_EVENTS:
     237                async_msg_1(dsp->event_exchange,
     238                    PCM_EVENT_FRAMES_PLAYED, dsp->active.frame_count);
     239        case DSP_PLAYBACK_NOEVENTS:
     240#ifndef AUTO_DMA_MODE
     241        sb_dsp_start_active(dsp, SINGLE_DMA_16B_DA);
     242#endif
     243                break;
     244        case DSP_CAPTURE_ACTIVE_EVENTS:
     245                async_msg_1(dsp->event_exchange,
     246                    PCM_EVENT_FRAMES_CAPTURED, dsp->active.frame_count);
     247        case DSP_CAPTURE_NOEVENTS:
     248#ifndef AUTO_DMA_MODE
     249        sb_dsp_start_active(dsp, SINGLE_DMA_16B_DA);
     250#endif
     251                break;
     252        default:
     253                ddf_log_warning("Interrupt while DSP not active");
    250254        }
    251255}
     
    273277int sb_dsp_get_buffer_position(sb_dsp_t *dsp, size_t *pos)
    274278{
    275         if (!dsp->buffer.data)
     279        if (dsp->state == DSP_NO_BUFFER)
    276280                return ENOENT;
    277281
     282        assert(dsp->buffer.data);
    278283        async_sess_t *sess = devman_parent_device_connect(EXCHANGE_ATOMIC,
    279284            dsp->sb_dev->handle, IPC_FLAG_BLOCKING);
     
    314319}
    315320
     321int sb_dsp_set_event_session(sb_dsp_t *dsp, async_sess_t *session)
     322{
     323        assert(dsp);
     324        if (dsp->event_session)
     325                return EBUSY;
     326        dsp->event_session = session;
     327        ddf_log_debug("Set event session to %p.", session);
     328        return EOK;
     329}
     330
     331async_sess_t * sb_dsp_get_event_session(sb_dsp_t *dsp)
     332{
     333        assert(dsp);
     334        ddf_log_debug("Get event session: %p.", dsp->event_session);
     335        return dsp->event_session;
     336}
     337
    316338int sb_dsp_get_buffer(sb_dsp_t *dsp, void **buffer, size_t *size)
    317339{
     
    321343        /* buffer is already setup by for someone, refuse to work until
    322344         * it's released */
    323         if (dsp->buffer.data)
     345        if (dsp->state != DSP_NO_BUFFER)
    324346                return EBUSY;
     347        assert(dsp->buffer.data == NULL);
    325348
    326349        const int ret = sb_setup_buffer(dsp, *size);
     
    333356                if (size)
    334357                        *size = dsp->buffer.size;
     358                sb_dsp_change_state(dsp, DSP_READY);
    335359        }
    336360        return ret;
    337361}
    338362
    339 int sb_dsp_set_event_session(sb_dsp_t *dsp, async_sess_t *session)
    340 {
    341         assert(dsp);
    342         if (dsp->event_session)
    343                 return EBUSY;
    344         dsp->event_session = session;
    345         ddf_log_debug("Set event session to %p.", session);
    346         return EOK;
    347 }
    348 
    349 async_sess_t * sb_dsp_get_event_session(sb_dsp_t *dsp)
    350 {
    351         assert(dsp);
    352         ddf_log_debug("Get event session: %p.", dsp->event_session);
    353         return dsp->event_session;
    354 }
    355 
    356363int sb_dsp_release_buffer(sb_dsp_t *dsp)
    357364{
    358365        assert(dsp);
    359         sb_clear_buffer(dsp);
    360         async_exchange_end(dsp->event_exchange);
    361         dsp->event_exchange = NULL;
    362         if (dsp->event_session)
    363                 async_hangup(dsp->event_session);
    364         dsp->event_session = NULL;
     366        if (dsp->state != DSP_READY && dsp->state != DSP_STOPPED)
     367                return EINVAL;
     368        assert(dsp->buffer.data);
     369        dmamem_unmap_anonymous(dsp->buffer.data);
     370        dsp->buffer.data = NULL;
     371        dsp->buffer.size = 0;
    365372        ddf_log_debug("DSP buffer released.");
     373        sb_dsp_change_state(dsp, DSP_NO_BUFFER);
    366374        return EOK;
    367375}
     
    388396                if (!dsp->event_exchange)
    389397                        return ENOMEM;
    390                 dsp->ignore_interrupts = false;
    391398        }
    392399
     
    409416            sampling_rate / (dsp->active.samples * channels));
    410417
    411         dsp->status = DSP_PLAYBACK;
     418        sb_dsp_change_state(dsp,
     419            frames ? DSP_PLAYBACK_ACTIVE_EVENTS : DSP_PLAYBACK_NOEVENTS);
    412420
    413421        return EOK;
     
    422430        async_exchange_end(dsp->event_exchange);
    423431        dsp->event_exchange = NULL;
     432        sb_dsp_change_state(dsp, DSP_STOPPED);
    424433        return EOK;
    425434}
     
    445454                if (!dsp->event_exchange)
    446455                        return ENOMEM;
    447                 dsp->ignore_interrupts = false;
    448456        }
    449457
     
    465473            "(~1/%u sec)", dsp->active.samples,
    466474            sampling_rate / (dsp->active.samples * channels));
    467         dsp->status = DSP_CAPTURE;
    468 
     475        sb_dsp_change_state(dsp,
     476            frames ? DSP_CAPTURE_ACTIVE_EVENTS : DSP_CAPTURE_NOEVENTS);
    469477        return EOK;
    470478}
     
    478486        async_exchange_end(dsp->event_exchange);
    479487        dsp->event_exchange = NULL;
     488        sb_dsp_change_state(dsp, DSP_STOPPED);
    480489        return EOK;
    481490}
Note: See TracChangeset for help on using the changeset viewer.