Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: Zlib
  2
  3#include "../zlib_inflate/inflate.h"
  4#include "dfltcc_util.h"
  5#include "dfltcc.h"
  6#include <asm/setup.h>
  7#include <linux/export.h>
  8#include <linux/zutil.h>
  9
 10/*
 11 * Expand.
 12 */
 13int dfltcc_can_inflate(
 14    z_streamp strm
 15)
 16{
 17    struct inflate_state *state = (struct inflate_state *)strm->state;
 18    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
 19
 20    /* Check for kernel dfltcc command line parameter */
 21    if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED ||
 22            zlib_dfltcc_support == ZLIB_DFLTCC_DEFLATE_ONLY)
 23        return 0;
 24
 25    /* Unsupported compression settings */
 26    if (state->wbits != HB_BITS)
 27        return 0;
 28
 29    /* Unsupported hardware */
 30    return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) &&
 31               is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);
 32}
 33EXPORT_SYMBOL(dfltcc_can_inflate);
 34
 35static int dfltcc_was_inflate_used(
 36    z_streamp strm
 37)
 38{
 39    struct inflate_state *state = (struct inflate_state *)strm->state;
 40    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
 41
 42    return !param->nt;
 43}
 44
 45static int dfltcc_inflate_disable(
 46    z_streamp strm
 47)
 48{
 49    struct inflate_state *state = (struct inflate_state *)strm->state;
 50    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
 51
 52    if (!dfltcc_can_inflate(strm))
 53        return 0;
 54    if (dfltcc_was_inflate_used(strm))
 55        /* DFLTCC has already decompressed some data. Since there is not
 56         * enough information to resume decompression in software, the call
 57         * must fail.
 58         */
 59        return 1;
 60    /* DFLTCC was not used yet - decompress in software */
 61    memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
 62    return 0;
 63}
 64
 65static dfltcc_cc dfltcc_xpnd(
 66    z_streamp strm
 67)
 68{
 69    struct inflate_state *state = (struct inflate_state *)strm->state;
 70    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
 71    size_t avail_in = strm->avail_in;
 72    size_t avail_out = strm->avail_out;
 73    dfltcc_cc cc;
 74
 75    cc = dfltcc(DFLTCC_XPND | HBT_CIRCULAR,
 76                param, &strm->next_out, &avail_out,
 77                &strm->next_in, &avail_in, state->window);
 78    strm->avail_in = avail_in;
 79    strm->avail_out = avail_out;
 80    return cc;
 81}
 82
 83dfltcc_inflate_action dfltcc_inflate(
 84    z_streamp strm,
 85    int flush,
 86    int *ret
 87)
 88{
 89    struct inflate_state *state = (struct inflate_state *)strm->state;
 90    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
 91    struct dfltcc_param_v0 *param = &dfltcc_state->param;
 92    dfltcc_cc cc;
 93
 94    if (flush == Z_BLOCK) {
 95        /* DFLTCC does not support stopping on block boundaries */
 96        if (dfltcc_inflate_disable(strm)) {
 97            *ret = Z_STREAM_ERROR;
 98            return DFLTCC_INFLATE_BREAK;
 99        } else
100            return DFLTCC_INFLATE_SOFTWARE;
101    }
102
103    if (state->last) {
104        if (state->bits != 0) {
105            strm->next_in++;
106            strm->avail_in--;
107            state->bits = 0;
108        }
109        state->mode = CHECK;
110        return DFLTCC_INFLATE_CONTINUE;
111    }
112
113    if (strm->avail_in == 0 && !param->cf)
114        return DFLTCC_INFLATE_BREAK;
115
116    if (!state->window || state->wsize == 0) {
117        state->mode = MEM;
118        return DFLTCC_INFLATE_CONTINUE;
119    }
120
121    /* Translate stream to parameter block */
122    param->cvt = CVT_ADLER32;
123    param->sbb = state->bits;
124    param->hl = state->whave; /* Software and hardware history formats match */
125    param->ho = (state->write - state->whave) & ((1 << HB_BITS) - 1);
126    if (param->hl)
127        param->nt = 0; /* Honor history for the first block */
128    param->cv = state->check;
129
130    /* Inflate */
131    do {
132        cc = dfltcc_xpnd(strm);
133    } while (cc == DFLTCC_CC_AGAIN);
134
135    /* Translate parameter block to stream */
136    strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
137    state->last = cc == DFLTCC_CC_OK;
138    state->bits = param->sbb;
139    state->whave = param->hl;
140    state->write = (param->ho + param->hl) & ((1 << HB_BITS) - 1);
141    state->check = param->cv;
142    if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {
143        /* Report an error if stream is corrupted */
144        state->mode = BAD;
145        return DFLTCC_INFLATE_CONTINUE;
146    }
147    state->mode = TYPEDO;
148    /* Break if operands are exhausted, otherwise continue looping */
149    return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ?
150        DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE;
151}
152EXPORT_SYMBOL(dfltcc_inflate);