root/drivers/media/platform/qcom/venus/hfi_parser.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. init_codecs
  2. for_each_codec
  3. fill_buf_mode
  4. parse_alloc_mode
  5. fill_profile_level
  6. parse_profile_level
  7. fill_caps
  8. parse_caps
  9. fill_raw_fmts
  10. parse_raw_formats
  11. parse_codecs
  12. parse_max_sessions
  13. parse_codecs_mask
  14. parser_init
  15. parser_fini
  16. hfi_parser

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2018 Linaro Ltd.
   4  *
   5  * Author: Stanimir Varbanov <stanimir.varbanov@linaro.org>
   6  */
   7 #include <linux/bitops.h>
   8 #include <linux/kernel.h>
   9 
  10 #include "core.h"
  11 #include "hfi_helper.h"
  12 #include "hfi_parser.h"
  13 
  14 typedef void (*func)(struct venus_caps *cap, const void *data,
  15                      unsigned int size);
  16 
  17 static void init_codecs(struct venus_core *core)
  18 {
  19         struct venus_caps *caps = core->caps, *cap;
  20         unsigned long bit;
  21 
  22         for_each_set_bit(bit, &core->dec_codecs, MAX_CODEC_NUM) {
  23                 cap = &caps[core->codecs_count++];
  24                 cap->codec = BIT(bit);
  25                 cap->domain = VIDC_SESSION_TYPE_DEC;
  26                 cap->valid = false;
  27         }
  28 
  29         for_each_set_bit(bit, &core->enc_codecs, MAX_CODEC_NUM) {
  30                 cap = &caps[core->codecs_count++];
  31                 cap->codec = BIT(bit);
  32                 cap->domain = VIDC_SESSION_TYPE_ENC;
  33                 cap->valid = false;
  34         }
  35 }
  36 
  37 static void for_each_codec(struct venus_caps *caps, unsigned int caps_num,
  38                            u32 codecs, u32 domain, func cb, void *data,
  39                            unsigned int size)
  40 {
  41         struct venus_caps *cap;
  42         unsigned int i;
  43 
  44         for (i = 0; i < caps_num; i++) {
  45                 cap = &caps[i];
  46                 if (cap->valid && cap->domain == domain)
  47                         continue;
  48                 if (cap->codec & codecs && cap->domain == domain)
  49                         cb(cap, data, size);
  50         }
  51 }
  52 
  53 static void
  54 fill_buf_mode(struct venus_caps *cap, const void *data, unsigned int num)
  55 {
  56         const u32 *type = data;
  57 
  58         if (*type == HFI_BUFFER_MODE_DYNAMIC)
  59                 cap->cap_bufs_mode_dynamic = true;
  60 }
  61 
  62 static void
  63 parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data)
  64 {
  65         struct hfi_buffer_alloc_mode_supported *mode = data;
  66         u32 num_entries = mode->num_entries;
  67         u32 *type;
  68 
  69         if (num_entries > MAX_ALLOC_MODE_ENTRIES)
  70                 return;
  71 
  72         type = mode->data;
  73 
  74         while (num_entries--) {
  75                 if (mode->buffer_type == HFI_BUFFER_OUTPUT ||
  76                     mode->buffer_type == HFI_BUFFER_OUTPUT2)
  77                         for_each_codec(core->caps, ARRAY_SIZE(core->caps),
  78                                        codecs, domain, fill_buf_mode, type, 1);
  79 
  80                 type++;
  81         }
  82 }
  83 
  84 static void fill_profile_level(struct venus_caps *cap, const void *data,
  85                                unsigned int num)
  86 {
  87         const struct hfi_profile_level *pl = data;
  88 
  89         memcpy(&cap->pl[cap->num_pl], pl, num * sizeof(*pl));
  90         cap->num_pl += num;
  91 }
  92 
  93 static void
  94 parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data)
  95 {
  96         struct hfi_profile_level_supported *pl = data;
  97         struct hfi_profile_level *proflevel = pl->profile_level;
  98         struct hfi_profile_level pl_arr[HFI_MAX_PROFILE_COUNT] = {};
  99 
 100         if (pl->profile_count > HFI_MAX_PROFILE_COUNT)
 101                 return;
 102 
 103         memcpy(pl_arr, proflevel, pl->profile_count * sizeof(*proflevel));
 104 
 105         for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain,
 106                        fill_profile_level, pl_arr, pl->profile_count);
 107 }
 108 
 109 static void
 110 fill_caps(struct venus_caps *cap, const void *data, unsigned int num)
 111 {
 112         const struct hfi_capability *caps = data;
 113 
 114         memcpy(&cap->caps[cap->num_caps], caps, num * sizeof(*caps));
 115         cap->num_caps += num;
 116 }
 117 
 118 static void
 119 parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data)
 120 {
 121         struct hfi_capabilities *caps = data;
 122         struct hfi_capability *cap = caps->data;
 123         u32 num_caps = caps->num_capabilities;
 124         struct hfi_capability caps_arr[MAX_CAP_ENTRIES] = {};
 125 
 126         if (num_caps > MAX_CAP_ENTRIES)
 127                 return;
 128 
 129         memcpy(caps_arr, cap, num_caps * sizeof(*cap));
 130 
 131         for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain,
 132                        fill_caps, caps_arr, num_caps);
 133 }
 134 
 135 static void fill_raw_fmts(struct venus_caps *cap, const void *fmts,
 136                           unsigned int num_fmts)
 137 {
 138         const struct raw_formats *formats = fmts;
 139 
 140         memcpy(&cap->fmts[cap->num_fmts], formats, num_fmts * sizeof(*formats));
 141         cap->num_fmts += num_fmts;
 142 }
 143 
 144 static void
 145 parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data)
 146 {
 147         struct hfi_uncompressed_format_supported *fmt = data;
 148         struct hfi_uncompressed_plane_info *pinfo = fmt->plane_info;
 149         struct hfi_uncompressed_plane_constraints *constr;
 150         struct raw_formats rawfmts[MAX_FMT_ENTRIES] = {};
 151         u32 entries = fmt->format_entries;
 152         unsigned int i = 0;
 153         u32 num_planes;
 154 
 155         while (entries) {
 156                 num_planes = pinfo->num_planes;
 157 
 158                 rawfmts[i].fmt = pinfo->format;
 159                 rawfmts[i].buftype = fmt->buffer_type;
 160                 i++;
 161 
 162                 if (pinfo->num_planes > MAX_PLANES)
 163                         break;
 164 
 165                 pinfo = (void *)pinfo + sizeof(*constr) * num_planes +
 166                         2 * sizeof(u32);
 167                 entries--;
 168         }
 169 
 170         for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain,
 171                        fill_raw_fmts, rawfmts, i);
 172 }
 173 
 174 static void parse_codecs(struct venus_core *core, void *data)
 175 {
 176         struct hfi_codec_supported *codecs = data;
 177 
 178         core->dec_codecs = codecs->dec_codecs;
 179         core->enc_codecs = codecs->enc_codecs;
 180 
 181         if (IS_V1(core)) {
 182                 core->dec_codecs &= ~HFI_VIDEO_CODEC_HEVC;
 183                 core->dec_codecs &= ~HFI_VIDEO_CODEC_SPARK;
 184                 core->enc_codecs &= ~HFI_VIDEO_CODEC_HEVC;
 185         }
 186 }
 187 
 188 static void parse_max_sessions(struct venus_core *core, const void *data)
 189 {
 190         const struct hfi_max_sessions_supported *sessions = data;
 191 
 192         core->max_sessions_supported = sessions->max_sessions;
 193 }
 194 
 195 static void parse_codecs_mask(u32 *codecs, u32 *domain, void *data)
 196 {
 197         struct hfi_codec_mask_supported *mask = data;
 198 
 199         *codecs = mask->codecs;
 200         *domain = mask->video_domains;
 201 }
 202 
 203 static void parser_init(struct venus_inst *inst, u32 *codecs, u32 *domain)
 204 {
 205         if (!inst || !IS_V1(inst->core))
 206                 return;
 207 
 208         *codecs = inst->hfi_codec;
 209         *domain = inst->session_type;
 210 }
 211 
 212 static void parser_fini(struct venus_inst *inst, u32 codecs, u32 domain)
 213 {
 214         struct venus_caps *caps, *cap;
 215         unsigned int i;
 216         u32 dom;
 217 
 218         if (!inst || !IS_V1(inst->core))
 219                 return;
 220 
 221         caps = inst->core->caps;
 222         dom = inst->session_type;
 223 
 224         for (i = 0; i < MAX_CODEC_NUM; i++) {
 225                 cap = &caps[i];
 226                 if (cap->codec & codecs && cap->domain == dom)
 227                         cap->valid = true;
 228         }
 229 }
 230 
 231 u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf,
 232                u32 size)
 233 {
 234         unsigned int words_count = size >> 2;
 235         u32 *word = buf, *data, codecs = 0, domain = 0;
 236 
 237         if (size % 4)
 238                 return HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
 239 
 240         parser_init(inst, &codecs, &domain);
 241 
 242         while (words_count) {
 243                 data = word + 1;
 244 
 245                 switch (*word) {
 246                 case HFI_PROPERTY_PARAM_CODEC_SUPPORTED:
 247                         parse_codecs(core, data);
 248                         init_codecs(core);
 249                         break;
 250                 case HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED:
 251                         parse_max_sessions(core, data);
 252                         break;
 253                 case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED:
 254                         parse_codecs_mask(&codecs, &domain, data);
 255                         break;
 256                 case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
 257                         parse_raw_formats(core, codecs, domain, data);
 258                         break;
 259                 case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED:
 260                         parse_caps(core, codecs, domain, data);
 261                         break;
 262                 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED:
 263                         parse_profile_level(core, codecs, domain, data);
 264                         break;
 265                 case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED:
 266                         parse_alloc_mode(core, codecs, domain, data);
 267                         break;
 268                 default:
 269                         break;
 270                 }
 271 
 272                 word++;
 273                 words_count--;
 274         }
 275 
 276         parser_fini(inst, codecs, domain);
 277 
 278         return HFI_ERR_NONE;
 279 }

/* [<][>][^][v][top][bottom][index][help] */