blob: 3cbdee049ea40ee0851dbc42a5d9a0af04849fea [file] [log] [blame]
Srinu Gorlecf8c6752018-01-19 18:36:13 +05301/* Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/module.h>
14#include "governor.h"
15#include "fixedpoint.h"
16#include "../msm_vidc_internal.h"
17#include "../msm_vidc_debug.h"
18#include "../vidc_hfi_api.h"
19
20static bool debug;
21module_param(debug, bool, 0644);
22
23enum governor_mode {
24 GOVERNOR_DDR,
25 GOVERNOR_VMEM,
26 GOVERNOR_VMEM_PLUS,
27};
28
29struct governor {
30 enum governor_mode mode;
31 struct devfreq_governor devfreq_gov;
32};
33
34enum scenario {
35 SCENARIO_WORST,
36 SCENARIO_SUSTAINED_WORST,
37 SCENARIO_AVERAGE,
38 SCENARIO_MAX,
39};
40
41/*
42 * Minimum dimensions that the governor is willing to calculate
43 * bandwidth for. This means that anything bandwidth(0, 0) ==
44 * bandwidth(BASELINE_DIMENSIONS.width, BASELINE_DIMENSIONS.height)
45 */
46const struct {
47 int height, width;
48} BASELINE_DIMENSIONS = {
49 .width = 1280,
50 .height = 720,
51};
52
53/*
54 * These are hardcoded AB values that the governor votes for in certain
55 * situations, where a certain bus frequency is desired. It isn't exactly
56 * scalable since different platforms have different bus widths, but we'll
57 * deal with that in the future.
58 */
59const unsigned long NOMINAL_BW_MBPS = 6000 /* ideally 320 Mhz */,
60 SVS_BW_MBPS = 2000 /* ideally 100 Mhz */;
61
62/* converts Mbps to bps (the "b" part can be bits or bytes based on context) */
63#define kbps(__mbps) ((__mbps) * 1000)
64#define bps(__mbps) (kbps(__mbps) * 1000)
65
66#define GENERATE_SCENARIO_PROFILE(__average, __worst) { \
67 [SCENARIO_AVERAGE] = (__average), \
68 [SCENARIO_WORST] = (__worst), \
69 [SCENARIO_SUSTAINED_WORST] = (__worst), \
70}
71
72#define GENERATE_COMPRESSION_PROFILE(__bpp, __average, __worst) { \
73 .bpp = __bpp, \
74 .ratio = GENERATE_SCENARIO_PROFILE(__average, __worst), \
75}
76
77/*
78 * The below table is a structural representation of the following table:
79 * Resolution | Bitrate | Compression Ratio |
80 * ............|............|.........................................|
81 * Width Height|Average High|Avg_8bpc Worst_8bpc Avg_10bpc Worst_10bpc|
82 * 1280 720| 7 14| 1.69 1.28 1.49 1.23|
83 * 1920 1080| 20 40| 1.69 1.28 1.49 1.23|
84 * 2560 1440| 32 64| 2.2 1.26 1.97 1.22|
85 * 3840 2160| 42 84| 2.2 1.26 1.97 1.22|
86 * 4096 2160| 44 88| 2.2 1.26 1.97 1.22|
87 * 4096 2304| 48 96| 2.2 1.26 1.97 1.22|
88 */
89#define COMPRESSION_RATIO_MAX 2
90static struct lut {
91 int frame_size; /* width x height */
92 unsigned long bitrate[SCENARIO_MAX];
93 struct {
94 int bpp;
95 fp_t ratio[SCENARIO_MAX];
96 } compression_ratio[COMPRESSION_RATIO_MAX];
97} const LUT[] = {
98 {
99 .frame_size = 1280 * 720,
100 .bitrate = GENERATE_SCENARIO_PROFILE(7, 14),
101 .compression_ratio = {
102 GENERATE_COMPRESSION_PROFILE(8,
103 FP(1, 69, 100),
104 FP(1, 28, 100)),
105 GENERATE_COMPRESSION_PROFILE(10,
106 FP(1, 49, 100),
107 FP(1, 23, 100)),
108 }
109 },
110 {
111 .frame_size = 1920 * 1088,
112 .bitrate = GENERATE_SCENARIO_PROFILE(20, 40),
113 .compression_ratio = {
114 GENERATE_COMPRESSION_PROFILE(8,
115 FP(1, 69, 100),
116 FP(1, 28, 100)),
117 GENERATE_COMPRESSION_PROFILE(10,
118 FP(1, 49, 100),
119 FP(1, 23, 100)),
120 }
121 },
122 {
123 .frame_size = 2560 * 1440,
124 .bitrate = GENERATE_SCENARIO_PROFILE(32, 64),
125 .compression_ratio = {
126 GENERATE_COMPRESSION_PROFILE(8,
127 FP(2, 20, 100),
128 FP(1, 26, 100)),
129 GENERATE_COMPRESSION_PROFILE(10,
130 FP(1, 97, 100),
131 FP(1, 22, 100)),
132 }
133 },
134 {
135 .frame_size = 3840 * 2160,
136 .bitrate = GENERATE_SCENARIO_PROFILE(42, 84),
137 .compression_ratio = {
138 GENERATE_COMPRESSION_PROFILE(8,
139 FP(2, 20, 100),
140 FP(1, 26, 100)),
141 GENERATE_COMPRESSION_PROFILE(10,
142 FP(1, 97, 100),
143 FP(1, 22, 100)),
144 }
145 },
146 {
147 .frame_size = 4096 * 2160,
148 .bitrate = GENERATE_SCENARIO_PROFILE(44, 88),
149 .compression_ratio = {
150 GENERATE_COMPRESSION_PROFILE(8,
151 FP(2, 20, 100),
152 FP(1, 26, 100)),
153 GENERATE_COMPRESSION_PROFILE(10,
154 FP(1, 97, 100),
155 FP(1, 22, 100)),
156 }
157 },
158 {
159 .frame_size = 4096 * 2304,
160 .bitrate = GENERATE_SCENARIO_PROFILE(48, 96),
161 .compression_ratio = {
162 GENERATE_COMPRESSION_PROFILE(8,
163 FP(2, 20, 100),
164 FP(1, 26, 100)),
165 GENERATE_COMPRESSION_PROFILE(10,
166 FP(1, 97, 100),
167 FP(1, 22, 100)),
168 }
169 },
170};
171
172static struct lut const *__lut(int width, int height)
173{
174 int frame_size = height * width, c = 0;
175
176 do {
177 if (LUT[c].frame_size >= frame_size)
178 return &LUT[c];
179 } while (++c < ARRAY_SIZE(LUT));
180
181 return &LUT[ARRAY_SIZE(LUT) - 1];
182}
183
184static fp_t __compression_ratio(struct lut const *entry, int bpp,
185 enum scenario s)
186{
187 int c = 0;
188
189 for (c = 0; c < COMPRESSION_RATIO_MAX; ++c) {
190 if (entry->compression_ratio[c].bpp == bpp)
191 return entry->compression_ratio[c].ratio[s];
192 }
193
194 WARN(true, "Shouldn't be here, LUT possibly corrupted?\n");
195 return FP_ZERO; /* impossible */
196}
197
198#define DUMP_HEADER_MAGIC 0xdeadbeef
199#define DUMP_FP_FMT "%FP" /* special format for fp_t */
200struct dump {
201 char *key;
202 char *format;
203 size_t val;
204};
205
206static void __dump(struct dump dump[], int len)
207{
208 int c = 0;
209
210 for (c = 0; c < len; ++c) {
211 char format_line[128] = "", formatted_line[128] = "";
212
213 if (dump[c].val == DUMP_HEADER_MAGIC) {
214 snprintf(formatted_line, sizeof(formatted_line), "%s\n",
215 dump[c].key);
216 } else {
217 bool fp_format = !strcmp(dump[c].format, DUMP_FP_FMT);
218
219 if (!fp_format) {
220 snprintf(format_line, sizeof(format_line),
221 " %-35s: %s\n", dump[c].key,
222 dump[c].format);
223 snprintf(formatted_line, sizeof(formatted_line),
224 format_line, dump[c].val);
225 } else {
226 size_t integer_part, fractional_part;
227
228 integer_part = fp_int(dump[c].val);
229 fractional_part = fp_frac(dump[c].val);
230 snprintf(formatted_line, sizeof(formatted_line),
231 " %-35s: %zd + %zd/%zd\n",
232 dump[c].key, integer_part,
233 fractional_part,
234 fp_frac_base());
235
236
237 }
238 }
239
240 dprintk(VIDC_DBG, "%s", formatted_line);
241 }
242}
243
244static unsigned long __calculate_vpe(struct vidc_bus_vote_data *d,
245 enum governor_mode gm)
246{
247 return 0;
248}
249
250static bool __ubwc(enum hal_uncompressed_format f)
251{
252 switch (f) {
253 case HAL_COLOR_FORMAT_NV12_UBWC:
254 case HAL_COLOR_FORMAT_NV12_TP10_UBWC:
255 return true;
256 default:
257 return false;
258 }
259}
260
261static int __bpp(enum hal_uncompressed_format f)
262{
263 switch (f) {
264 case HAL_COLOR_FORMAT_NV12:
265 case HAL_COLOR_FORMAT_NV21:
266 case HAL_COLOR_FORMAT_NV12_UBWC:
267 return 8;
268 case HAL_COLOR_FORMAT_NV12_TP10_UBWC:
269 return 10;
270 default:
271 dprintk(VIDC_ERR,
272 "What's this? We don't support this colorformat (%x)",
273 f);
274 return INT_MAX;
275 }
276}
277
278static unsigned long __calculate_vmem_plus_ab(struct vidc_bus_vote_data *d)
279{
280 unsigned long i = 0, vmem_plus = 0;
281
282 if (!d->imem_ab_tbl || !d->imem_ab_tbl_size) {
283 vmem_plus = 1; /* Vote for the min ab value */
284 goto exit;
285 }
286
287 /* Pick up vmem frequency based on venus core frequency */
288 for (i = 0; i < d->imem_ab_tbl_size; i++) {
289 if (d->imem_ab_tbl[i].core_freq == d->core_freq) {
290 vmem_plus = d->imem_ab_tbl[i].imem_ab;
291 break;
292 }
293 }
294
295 /* Incase we get an unsupported freq throw a warning
296 * and set ab to the minimum value.
297 */
298 if (!vmem_plus) {
299 vmem_plus = 1;
300 dprintk(VIDC_WARN,
301 "could not calculate vmem ab value due to core freq mismatch\n");
302 WARN_ON(VIDC_DBG_WARN_ENABLE);
303 }
304
305exit:
306 return vmem_plus;
307}
308
309
310static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d,
311 enum governor_mode gm) {
312 /*
313 * XXX: Don't fool around with any of the hardcoded numbers unless you
314 * know /exactly/ what you're doing. Many of these numbers are
315 * measured heuristics and hardcoded numbers taken from the firmware.
316 */
317 /* Decoder parameters */
318 enum scenario scenario;
319 int width, height, lcu_size, dpb_bpp, opb_bpp, fps;
320 bool unified_dpb_opb, dpb_compression_enabled, opb_compression_enabled;
321 fp_t dpb_opb_scaling_ratio, dpb_compression_factor,
322 opb_compression_factor, qsmmu_bw_overhead_factor;
323 int vmem_size; /* in kB */
324
325 /* Derived parameters */
326 int lcu_per_frame, tnbr_per_lcu_10bpc, tnbr_per_lcu_8bpc, tnbr_per_lcu,
327 colocated_bytes_per_lcu, vmem_line_buffer, vmem_chroma_cache,
328 vmem_luma_cache, vmem_chroma_luma_cache;
329 unsigned long bitrate;
330 fp_t bins_to_bit_factor, dpb_write_factor, ten_bpc_packing_factor,
331 ten_bpc_bpp_factor, vsp_read_factor, vsp_write_factor,
332 ocmem_usage_lcu_factor, ref_ocmem_bw_factor_read,
333 ref_ocmem_bw_factor_write, bw_for_1x_8bpc, dpb_bw_for_1x,
334 motion_vector_complexity, row_cache_penalty, opb_bw;
335
336 /* Output parameters */
337 struct {
338 fp_t vsp_read, vsp_write, collocated_read, collocated_write,
339 line_buffer_read, line_buffer_write, recon_read,
340 recon_write, opb_read, opb_write, dpb_read, dpb_write,
341 total;
342 } ddr, vmem;
343
344 unsigned long ret = 0;
345
346 /* Decoder parameters setup */
347 scenario = SCENARIO_WORST;
348
349 width = max(d->width, BASELINE_DIMENSIONS.width);
350 height = max(d->height, BASELINE_DIMENSIONS.height);
351
352 lcu_size = 32;
353
354 dpb_bpp = d->num_formats >= 1 ? __bpp(d->color_formats[0]) : INT_MAX;
355 opb_bpp = d->num_formats >= 2 ? __bpp(d->color_formats[1]) : dpb_bpp;
356
357 fps = d->fps;
358
359 unified_dpb_opb = d->num_formats == 1;
360
361 dpb_opb_scaling_ratio = FP_ONE;
362
363 dpb_compression_enabled = d->num_formats >= 1 &&
364 __ubwc(d->color_formats[0]);
365 opb_compression_enabled = d->num_formats >= 2 &&
366 __ubwc(d->color_formats[1]);
367
368 dpb_compression_factor = !dpb_compression_enabled ? FP_ONE :
369 __compression_ratio(__lut(width, height), dpb_bpp, scenario);
370
371 opb_compression_factor = !opb_compression_enabled ? FP_ONE :
372 __compression_ratio(__lut(width, height), opb_bpp, scenario);
373
374 vmem_size = 512; /* in kB */
375
376 /* Derived parameters setup */
377 lcu_per_frame = DIV_ROUND_UP(width, lcu_size) *
378 DIV_ROUND_UP(height, lcu_size);
379
380 bitrate = __lut(width, height)->bitrate[scenario];
381
382 bins_to_bit_factor = FP(1, 60, 100);
383
384 dpb_write_factor = scenario == SCENARIO_AVERAGE ?
385 FP_ONE : FP(1, 5, 100);
386
387 ten_bpc_packing_factor = FP(1, 67, 1000);
388 ten_bpc_bpp_factor = FP(1, 1, 4);
389
390 vsp_read_factor = bins_to_bit_factor + FP_INT(2);
391 vsp_write_factor = bins_to_bit_factor;
392
393 tnbr_per_lcu_10bpc = lcu_size == 16 ? 384 + 192 :
394 lcu_size == 32 ? 640 + 256 :
395 1280 + 384;
396 tnbr_per_lcu_8bpc = lcu_size == 16 ? 256 + 192 :
397 lcu_size == 32 ? 512 + 256 :
398 1024 + 384;
399 tnbr_per_lcu = dpb_bpp == 10 ? tnbr_per_lcu_10bpc : tnbr_per_lcu_8bpc;
400
401 colocated_bytes_per_lcu = lcu_size == 16 ? 16 :
402 lcu_size == 32 ? 64 : 256;
403
404 ocmem_usage_lcu_factor = lcu_size == 16 ? FP(1, 8, 10) :
405 lcu_size == 32 ? FP(1, 2, 10) :
406 FP_ONE;
407 ref_ocmem_bw_factor_read = vmem_size < 296 ? FP_ZERO :
408 vmem_size < 648 ? FP(0, 1, 4) :
409 FP(0, 55, 100);
410 ref_ocmem_bw_factor_write = vmem_size < 296 ? FP_ZERO :
411 vmem_size < 648 ? FP(0, 7, 10) :
412 FP(1, 4, 10);
413
414 /* Prelim b/w calculation */
415 bw_for_1x_8bpc = fp_mult(FP_INT(width * height * fps),
416 fp_mult(FP(1, 50, 100), dpb_write_factor));
417 bw_for_1x_8bpc = fp_div(bw_for_1x_8bpc, FP_INT(bps(1)));
418
419 dpb_bw_for_1x = dpb_bpp == 8 ? bw_for_1x_8bpc :
420 fp_mult(bw_for_1x_8bpc, fp_mult(ten_bpc_packing_factor,
421 ten_bpc_bpp_factor));
422 /* VMEM adjustments */
423 vmem_line_buffer = tnbr_per_lcu * DIV_ROUND_UP(width, lcu_size) / 1024;
424 vmem_chroma_cache = dpb_bpp == 10 ? 176 : 128;
425 vmem_luma_cache = dpb_bpp == 10 ? 353 : 256;
426 vmem_chroma_luma_cache = vmem_chroma_cache + vmem_luma_cache;
427
428 motion_vector_complexity = scenario == SCENARIO_AVERAGE ?
429 FP(2, 66, 100) : FP_INT(4);
430
431 row_cache_penalty = FP_ZERO;
432 if (vmem_size < vmem_line_buffer + vmem_chroma_cache)
433 row_cache_penalty = fp_mult(FP(0, 5, 100),
434 motion_vector_complexity);
435 else if (vmem_size < vmem_line_buffer + vmem_luma_cache)
436 row_cache_penalty = fp_mult(FP(0, 7, 100),
437 motion_vector_complexity);
438 else if (vmem_size < vmem_line_buffer + vmem_chroma_cache
439 + vmem_luma_cache)
440 row_cache_penalty = fp_mult(FP(0, 3, 100),
441 motion_vector_complexity);
442 else
443 row_cache_penalty = FP_ZERO;
444
445
446 opb_bw = unified_dpb_opb ? FP_ZERO :
447 fp_div(fp_div(bw_for_1x_8bpc, dpb_opb_scaling_ratio),
448 opb_compression_factor);
449
450 /* B/W breakdown on a per buffer type basis for VMEM */
451 vmem.vsp_read = FP_ZERO;
452 vmem.vsp_write = FP_ZERO;
453
454 vmem.collocated_read = FP_ZERO;
455 vmem.collocated_write = FP_ZERO;
456
457 vmem.line_buffer_read = FP_INT(tnbr_per_lcu *
458 lcu_per_frame * fps / bps(1));
459 vmem.line_buffer_write = vmem.line_buffer_read;
460
461 vmem.recon_read = FP_ZERO;
462 vmem.recon_write = FP_ZERO;
463
464 vmem.opb_read = FP_ZERO;
465 vmem.opb_write = FP_ZERO;
466
467 vmem.dpb_read = fp_mult(ocmem_usage_lcu_factor, fp_mult(
468 ref_ocmem_bw_factor_read,
469 dpb_bw_for_1x));
470 vmem.dpb_write = fp_mult(ocmem_usage_lcu_factor, fp_mult(
471 ref_ocmem_bw_factor_write,
472 dpb_bw_for_1x));
473
474 vmem.total = vmem.vsp_read + vmem.vsp_write +
475 vmem.collocated_read + vmem.collocated_write +
476 vmem.line_buffer_read + vmem.line_buffer_write +
477 vmem.recon_read + vmem.recon_write +
478 vmem.opb_read + vmem.opb_write +
479 vmem.dpb_read + vmem.dpb_write;
480
481 /*
482 * Attempt to force VMEM to a certain frequency for 4K
483 */
484 if (width * height * fps >= 3840 * 2160 * 60)
485 vmem.total = FP_INT(NOMINAL_BW_MBPS);
486 else if (width * height * fps >= 3840 * 2160 * 30)
487 vmem.total = FP_INT(SVS_BW_MBPS);
488
489 /* ........................................ for DDR */
490 ddr.vsp_read = fp_div(fp_mult(FP_INT(bitrate),
491 vsp_read_factor), FP_INT(8));
492 ddr.vsp_write = fp_div(fp_mult(FP_INT(bitrate),
493 vsp_write_factor), FP_INT(8));
494
495 ddr.collocated_read = FP_INT(lcu_per_frame *
496 colocated_bytes_per_lcu * fps / bps(1));
497 ddr.collocated_write = FP_INT(lcu_per_frame *
498 colocated_bytes_per_lcu * fps / bps(1));
499
500 ddr.line_buffer_read = vmem_size ? FP_ZERO : vmem.line_buffer_read;
501 ddr.line_buffer_write = vmem_size ? FP_ZERO : vmem.line_buffer_write;
502
503 ddr.recon_read = FP_ZERO;
504 ddr.recon_write = fp_div(dpb_bw_for_1x, dpb_compression_factor);
505
506 ddr.opb_read = FP_ZERO;
507 ddr.opb_write = opb_bw;
508
509 ddr.dpb_read = fp_div(fp_mult(dpb_bw_for_1x,
510 motion_vector_complexity + row_cache_penalty),
511 dpb_compression_factor);
512 ddr.dpb_write = FP_ZERO;
513
514 ddr.total = ddr.vsp_read + ddr.vsp_write +
515 ddr.collocated_read + ddr.collocated_write +
516 ddr.line_buffer_read + ddr.line_buffer_write +
517 ddr.recon_read + ddr.recon_write +
518 ddr.opb_read + ddr.opb_write +
519 ddr.dpb_read + ddr.dpb_write;
520
521 qsmmu_bw_overhead_factor = FP(1, 3, 100);
522 ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor);
523
524 /* Dump all the variables for easier debugging */
525 if (debug) {
526 struct dump dump[] = {
527 {"DECODER PARAMETERS", "", DUMP_HEADER_MAGIC},
528 {"content", "%d", scenario},
529 {"LCU size", "%d", lcu_size},
530 {"DPB bitdepth", "%d", dpb_bpp},
531 {"frame rate", "%d", fps},
532 {"DPB/OPB unified", "%d", unified_dpb_opb},
533 {"DPB/OPB downscaling ratio", DUMP_FP_FMT,
534 dpb_opb_scaling_ratio},
535 {"DPB compression", "%d", dpb_compression_enabled},
536 {"OPB compression", "%d", opb_compression_enabled},
537 {"DPB compression factor", DUMP_FP_FMT,
538 dpb_compression_factor},
539 {"OPB compression factor", DUMP_FP_FMT,
540 opb_compression_factor},
541 {"VMEM size", "%dkB", vmem_size},
542 {"frame width", "%d", width},
543 {"frame height", "%d", height},
544
545 {"DERIVED PARAMETERS (1)", "", DUMP_HEADER_MAGIC},
546 {"LCUs/frame", "%d", lcu_per_frame},
547 {"bitrate (Mbit/sec)", "%d", bitrate},
548 {"bins to bit factor", DUMP_FP_FMT, bins_to_bit_factor},
549 {"DPB write factor", DUMP_FP_FMT, dpb_write_factor},
550 {"10bpc packing factor", DUMP_FP_FMT,
551 ten_bpc_packing_factor},
552 {"10bpc,BPP factor", DUMP_FP_FMT, ten_bpc_bpp_factor},
553 {"VSP read factor", DUMP_FP_FMT, vsp_read_factor},
554 {"VSP write factor", DUMP_FP_FMT, vsp_write_factor},
555 {"TNBR/LCU_10bpc", "%d", tnbr_per_lcu_10bpc},
556 {"TNBR/LCU_8bpc", "%d", tnbr_per_lcu_8bpc},
557 {"TNBR/LCU", "%d", tnbr_per_lcu},
558 {"colocated bytes/LCU", "%d", colocated_bytes_per_lcu},
559 {"OCMEM usage LCU factor", DUMP_FP_FMT,
560 ocmem_usage_lcu_factor},
561 {"ref OCMEM b/w factor (read)", DUMP_FP_FMT,
562 ref_ocmem_bw_factor_read},
563 {"ref OCMEM b/w factor (write)", DUMP_FP_FMT,
564 ref_ocmem_bw_factor_write},
565 {"B/W for 1x (NV12 8bpc)", DUMP_FP_FMT, bw_for_1x_8bpc},
566 {"DPB B/W For 1x (NV12)", DUMP_FP_FMT, dpb_bw_for_1x},
567
568 {"VMEM", "", DUMP_HEADER_MAGIC},
569 {"line buffer", "%d", vmem_line_buffer},
570 {"chroma cache", "%d", vmem_chroma_cache},
571 {"luma cache", "%d", vmem_luma_cache},
572 {"luma & chroma cache", "%d", vmem_chroma_luma_cache},
573
574 {"DERIVED PARAMETERS (2)", "", DUMP_HEADER_MAGIC},
575 {"MV complexity", DUMP_FP_FMT, motion_vector_complexity},
576 {"row cache penalty", DUMP_FP_FMT, row_cache_penalty},
577 {"OPB B/W (single instance)", DUMP_FP_FMT, opb_bw},
578
579 {"INTERMEDIATE DDR B/W", "", DUMP_HEADER_MAGIC},
580 {"VSP read", DUMP_FP_FMT, ddr.vsp_read},
581 {"VSP write", DUMP_FP_FMT, ddr.vsp_write},
582 {"collocated read", DUMP_FP_FMT, ddr.collocated_read},
583 {"collocated write", DUMP_FP_FMT, ddr.collocated_write},
584 {"line buffer read", DUMP_FP_FMT, ddr.line_buffer_read},
585 {"line buffer write", DUMP_FP_FMT, ddr.line_buffer_write},
586 {"recon read", DUMP_FP_FMT, ddr.recon_read},
587 {"recon write", DUMP_FP_FMT, ddr.recon_write},
588 {"OPB read", DUMP_FP_FMT, ddr.opb_read},
589 {"OPB write", DUMP_FP_FMT, ddr.opb_write},
590 {"DPB read", DUMP_FP_FMT, ddr.dpb_read},
591 {"DPB write", DUMP_FP_FMT, ddr.dpb_write},
592
593 {"INTERMEDIATE VMEM B/W", "", DUMP_HEADER_MAGIC},
594 {"VSP read", "%d", vmem.vsp_read},
595 {"VSP write", DUMP_FP_FMT, vmem.vsp_write},
596 {"collocated read", DUMP_FP_FMT, vmem.collocated_read},
597 {"collocated write", DUMP_FP_FMT, vmem.collocated_write},
598 {"line buffer read", DUMP_FP_FMT, vmem.line_buffer_read},
599 {"line buffer write", DUMP_FP_FMT, vmem.line_buffer_write},
600 {"recon read", DUMP_FP_FMT, vmem.recon_read},
601 {"recon write", DUMP_FP_FMT, vmem.recon_write},
602 {"OPB read", DUMP_FP_FMT, vmem.opb_read},
603 {"OPB write", DUMP_FP_FMT, vmem.opb_write},
604 {"DPB read", DUMP_FP_FMT, vmem.dpb_read},
605 {"DPB write", DUMP_FP_FMT, vmem.dpb_write},
606 };
607 __dump(dump, ARRAY_SIZE(dump));
608 }
609
610 switch (gm) {
611 case GOVERNOR_DDR:
612 ret = kbps(fp_round(ddr.total));
613 break;
614 case GOVERNOR_VMEM:
615 ret = kbps(fp_round(vmem.total));
616 break;
617 case GOVERNOR_VMEM_PLUS:
618 ret = __calculate_vmem_plus_ab(d);
619 break;
620 default:
621 dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
622 }
623
624 return ret;
625}
626
627
628static unsigned long __calculate_encoder(struct vidc_bus_vote_data *d,
629 enum governor_mode gm)
630{
631 /*
632 * XXX: Don't fool around with any of the hardcoded numbers unless you
633 * know /exactly/ what you're doing. Many of these numbers are
634 * measured heuristics and hardcoded numbers taken from the firmware.
635 */
636 /* Encoder Parameters */
637 enum scenario scenario, bitrate_scenario;
638 enum hal_video_codec standard;
639 int width, height, fps, vmem_size;
640 enum hal_uncompressed_format dpb_color_format;
641 enum hal_uncompressed_format original_color_format;
642 bool dpb_compression_enabled, original_compression_enabled,
643 two_stage_encoding, low_power, rotation, cropping_or_scaling;
644 fp_t dpb_compression_factor, original_compression_factor,
645 qsmmu_bw_overhead_factor;
646 bool b_frames_enabled;
647
648 /* Derived Parameters */
649 int lcu_size;
650 enum gop {
651 GOP_IBBP,
652 GOP_IPPP,
653 } gop;
654 unsigned long bitrate;
655 fp_t bins_to_bit_factor, chroma_luma_factor_dpb, one_frame_bw_dpb,
656 chroma_luma_factor_original, one_frame_bw_original,
657 line_buffer_size_per_lcu, line_buffer_size, line_buffer_bw,
658 original_vmem_requirement, bw_increase_p, bw_increase_b;
659 int collocated_mv_per_lcu, max_transaction_size,
660 search_window_size_vertical_p, search_window_factor_p,
661 search_window_factor_bw_p, vmem_size_p, available_vmem_p,
662 search_window_size_vertical_b, search_window_factor_b,
663 search_window_factor_bw_b, vmem_size_b, available_vmem_b;
664
665 /* Output paramaters */
666 struct {
667 fp_t vsp_read, vsp_write, collocated_read, collocated_write,
668 line_buffer_read, line_buffer_write, original_read,
669 original_write, dpb_read, dpb_write, total;
670 } ddr, vmem;
671
672 unsigned long ret = 0;
673
674 /* Encoder Parameters setup */
675 scenario = SCENARIO_WORST;
676
677 standard = d->codec;
678 width = max(d->width, BASELINE_DIMENSIONS.width);
679 height = max(d->height, BASELINE_DIMENSIONS.height);
680
681 dpb_color_format = HAL_COLOR_FORMAT_NV12_UBWC;
682 original_color_format = d->num_formats >= 1 ?
683 d->color_formats[0] : HAL_UNUSED_COLOR;
684
685 fps = d->fps;
686 bitrate_scenario = SCENARIO_WORST;
687
688 dpb_compression_enabled = __ubwc(dpb_color_format);
689 original_compression_enabled = __ubwc(original_color_format);
690
691 two_stage_encoding = false;
692 low_power = d->power_mode == VIDC_POWER_LOW;
693 b_frames_enabled = false;
694
695 dpb_compression_factor = !dpb_compression_enabled ? FP_ONE :
696 __compression_ratio(__lut(width, height),
697 __bpp(dpb_color_format), scenario);
698 original_compression_factor = !original_compression_enabled ? FP_ONE :
699 __compression_ratio(__lut(width, height),
700 __bpp(original_color_format), scenario);
701
702 rotation = false;
703 cropping_or_scaling = false;
704 vmem_size = 512; /* in kB */
705
706 /* Derived Parameters */
707 lcu_size = 16;
708 gop = b_frames_enabled ? GOP_IBBP : GOP_IPPP;
709 bitrate = __lut(width, height)->bitrate[bitrate_scenario];
710 bins_to_bit_factor = FP(1, 6, 10);
711
712 /*
713 * FIXME: Minor color format related hack: a lot of the derived params
714 * depend on the YUV bitdepth as a variable. However, we don't have
715 * appropriate enums defined yet (hence no support). As a result omit
716 * a lot of the checks (which should look like the snippet below) in
717 * favour of hardcoding.
718 * dpb_color_format == YUV420 ? 0.5 :
719 * dpb_color_format == YUV422 ? 1.0 : 2.0
720 * Similar hacks are annotated inline in code with the string "CF hack"
721 * for documentation purposes.
722 */
723 chroma_luma_factor_dpb = FP(0, 1, 2);
724 one_frame_bw_dpb = fp_mult(FP_ONE + chroma_luma_factor_dpb,
725 fp_div(FP_INT(width * height * fps),
726 FP_INT(1000 * 1000)));
727
728 chroma_luma_factor_original = FP(0, 1, 2); /* XXX: CF hack */
729 one_frame_bw_original = fp_mult(FP_ONE + chroma_luma_factor_original,
730 fp_div(FP_INT(width * height * fps),
731 FP_INT(1000 * 1000)));
732
733 line_buffer_size_per_lcu = FP_ZERO;
734 if (lcu_size == 16)
735 line_buffer_size_per_lcu = FP_INT(128) + fp_mult(FP_INT(256),
736 FP_ONE /*XXX: CF hack */);
737 else
738 line_buffer_size_per_lcu = FP_INT(192) + fp_mult(FP_INT(512),
739 FP_ONE /*XXX: CF hack */);
740
741 line_buffer_size = fp_div(
742 fp_mult(FP_INT(width / lcu_size),
743 line_buffer_size_per_lcu),
744 FP_INT(1024));
745 line_buffer_bw = fp_mult(line_buffer_size,
746 fp_div(FP_INT((height / lcu_size /
747 (two_stage_encoding ? 2 : 1) - 1) * fps),
748 FP_INT(1000)));
749
750 collocated_mv_per_lcu = lcu_size == 16 ? 16 : 64;
751 max_transaction_size = 256;
752
753 original_vmem_requirement = FP_INT(3 *
754 (two_stage_encoding ? 2 : 1) * lcu_size);
755 original_vmem_requirement = fp_mult(original_vmem_requirement,
756 (FP_ONE + chroma_luma_factor_original));
757 original_vmem_requirement += FP_INT((cropping_or_scaling ? 3 : 0) * 2);
758 original_vmem_requirement = fp_mult(original_vmem_requirement,
759 FP_INT(max_transaction_size));
760 original_vmem_requirement = fp_div(original_vmem_requirement,
761 FP_INT(1024));
762
763 search_window_size_vertical_p = low_power ? 32 :
764 b_frames_enabled ? 80 :
765 width > 2048 ? 64 : 48;
766 search_window_factor_p = search_window_size_vertical_p * 2 / lcu_size;
767 search_window_factor_bw_p = !two_stage_encoding ?
768 search_window_size_vertical_p * 2 / lcu_size + 1 :
769 (search_window_size_vertical_p * 2 / lcu_size + 2) / 2;
770 vmem_size_p = (search_window_factor_p * width + 128 * 2) *
771 lcu_size / 2 / 1024; /* XXX: CF hack */
772 bw_increase_p = fp_mult(one_frame_bw_dpb,
773 FP_INT(search_window_factor_bw_p - 1) / 3);
774 available_vmem_p = min_t(int, 3, (vmem_size - fp_int(line_buffer_size) -
775 fp_int(original_vmem_requirement)) / vmem_size_p);
776
777 search_window_size_vertical_b = 48;
778 search_window_factor_b = search_window_size_vertical_b * 2 / lcu_size;
779 search_window_factor_bw_b = !two_stage_encoding ?
780 search_window_size_vertical_b * 2 / lcu_size + 1 :
781 (search_window_size_vertical_b * 2 / lcu_size + 2) / 2;
782 vmem_size_b = (search_window_factor_b * width + 128 * 2) * lcu_size /
783 2 / 1024;
784 bw_increase_b = fp_mult(one_frame_bw_dpb,
785 FP_INT((search_window_factor_bw_b - 1) / 3));
786 available_vmem_b = min_t(int, 6, (vmem_size - fp_int(line_buffer_size) -
787 fp_int(original_vmem_requirement)) / vmem_size_b);
788
789 /* Output parameters for DDR */
790 ddr.vsp_read = fp_mult(fp_div(FP_INT(bitrate), FP_INT(8)),
791 bins_to_bit_factor);
792 ddr.vsp_write = ddr.vsp_read + fp_div(FP_INT(bitrate), FP_INT(8));
793
794 ddr.collocated_read = fp_div(FP_INT(DIV_ROUND_UP(width, lcu_size) *
795 DIV_ROUND_UP(height, lcu_size) *
796 collocated_mv_per_lcu * fps), FP_INT(1000 * 1000));
797 ddr.collocated_write = ddr.collocated_read;
798
799 ddr.line_buffer_read = (FP_INT(vmem_size) >= line_buffer_size +
800 original_vmem_requirement) ? FP_ZERO : line_buffer_bw;
801 ddr.line_buffer_write = ddr.line_buffer_read;
802
803 ddr.original_read = fp_div(one_frame_bw_original,
804 original_compression_factor);
805 ddr.original_write = FP_ZERO;
806
807 ddr.dpb_read = FP_ZERO;
808 if (gop == GOP_IPPP) {
809 ddr.dpb_read = one_frame_bw_dpb + fp_mult(bw_increase_p,
810 FP_INT(3 - available_vmem_p));
811 } else if (scenario == SCENARIO_WORST ||
812 scenario == SCENARIO_SUSTAINED_WORST) {
813 ddr.dpb_read = fp_mult(one_frame_bw_dpb, FP_INT(2));
814 ddr.dpb_read += fp_mult(FP_INT(6 - available_vmem_b),
815 bw_increase_b);
816 } else {
817 fp_t part_p, part_b;
818
819 part_p = one_frame_bw_dpb + fp_mult(bw_increase_p,
820 FP_INT(3 - available_vmem_p));
821 part_p = fp_div(part_p, FP_INT(3));
822
823 part_b = fp_mult(one_frame_bw_dpb, 2) +
824 fp_mult(FP_INT(6 - available_vmem_b), bw_increase_b);
825 part_b = fp_mult(part_b, FP(0, 2, 3));
826
827 ddr.dpb_read = part_p + part_b;
828 }
829
830 ddr.dpb_read = fp_div(ddr.dpb_read, dpb_compression_factor);
831 ddr.dpb_write = fp_div(one_frame_bw_dpb, dpb_compression_factor);
832
833 ddr.total = ddr.vsp_read + ddr.vsp_write +
834 ddr.collocated_read + ddr.collocated_write +
835 ddr.line_buffer_read + ddr.line_buffer_write +
836 ddr.original_read + ddr.original_write +
837 ddr.dpb_read + ddr.dpb_write;
838
839 qsmmu_bw_overhead_factor = FP(1, 3, 100);
840 ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor);
841
842 /* ................. for VMEM */
843 vmem.vsp_read = FP_ZERO;
844 vmem.vsp_write = FP_ZERO;
845
846 vmem.collocated_read = FP_ZERO;
847 vmem.collocated_write = FP_ZERO;
848
849 vmem.line_buffer_read = line_buffer_bw - ddr.line_buffer_read;
850 vmem.line_buffer_write = vmem.line_buffer_read;
851
852 vmem.original_read = FP_INT(vmem_size) >= original_vmem_requirement ?
853 ddr.original_read : FP_ZERO;
854 vmem.original_write = vmem.original_read;
855
856 vmem.dpb_read = FP_ZERO;
857 if (gop == GOP_IPPP) {
858 fp_t temp = fp_mult(one_frame_bw_dpb,
859 FP_INT(search_window_factor_bw_p * available_vmem_p));
860 temp = fp_div(temp, FP_INT(3));
861
862 vmem.dpb_read = temp;
863 } else if (scenario != SCENARIO_AVERAGE) {
864 fp_t temp = fp_mult(one_frame_bw_dpb, FP_INT(2));
865
866 temp = fp_mult(temp, FP_INT(search_window_factor_bw_b *
867 available_vmem_b));
868 temp = fp_div(temp, FP_INT(6));
869
870 vmem.dpb_read = temp;
871 } else {
872 fp_t part_p, part_b;
873
874 part_p = fp_mult(one_frame_bw_dpb, FP_INT(
875 search_window_factor_bw_p *
876 available_vmem_p));
877 part_p = fp_div(part_p, FP_INT(3 * 3));
878
879 part_b = fp_mult(one_frame_bw_dpb, FP_INT(2 *
880 search_window_factor_bw_b *
881 available_vmem_b));
882 part_b = fp_div(part_b, FP_INT(6));
883 part_b = fp_mult(part_b, FP(0, 2, 3));
884
885 vmem.dpb_read = part_p + part_b;
886 }
887
888 vmem.dpb_write = FP_ZERO;
889 if (gop == GOP_IPPP) {
890 fp_t temp = fp_mult(one_frame_bw_dpb,
891 FP_INT(available_vmem_p));
892 temp = fp_div(temp, FP_INT(3));
893
894 vmem.dpb_write = temp;
895 } else if (scenario != SCENARIO_AVERAGE) {
896 fp_t temp = fp_mult(one_frame_bw_dpb,
897 FP_INT(2 * available_vmem_b));
898 temp = fp_div(temp, FP_INT(6));
899
900 vmem.dpb_write = temp;
901 } else {
902 fp_t part_b, part_p;
903
904 part_b = fp_mult(one_frame_bw_dpb, FP_INT(available_vmem_p));
905 part_b = fp_div(part_b, FP_INT(9));
906
907 part_p = fp_mult(one_frame_bw_dpb, FP_INT(
908 2 * available_vmem_b));
909 part_p = fp_div(part_p, FP_INT(6));
910 part_b = fp_mult(part_b, FP(0, 2, 3));
911
912 vmem.dpb_write = part_p + part_b;
913 }
914
915 vmem.total = vmem.vsp_read + vmem.vsp_write +
916 vmem.collocated_read + vmem.collocated_write +
917 vmem.line_buffer_read + vmem.line_buffer_write +
918 vmem.original_read + vmem.original_write +
919 vmem.dpb_read + vmem.dpb_write;
920
921 /*
922 * When in low power mode, attempt to force the VMEM clocks a certain
923 * frequency that DCVS would prefer
924 */
925 if (width * height >= 3840 * 2160 && low_power)
926 vmem.total = FP_INT(NOMINAL_BW_MBPS);
927
928 if (debug) {
929 struct dump dump[] = {
930 {"ENCODER PARAMETERS", "", DUMP_HEADER_MAGIC},
931 {"scenario", "%d", scenario},
932 {"standard", "%#x", standard},
933 {"width", "%d", width},
934 {"height", "%d", height},
935 {"DPB format", "%#x", dpb_color_format},
936 {"original frame format", "%#x", original_color_format},
937 {"fps", "%d", fps},
938 {"target bitrate", "%d", bitrate_scenario},
939 {"DPB compression enable", "%d", dpb_compression_enabled},
940 {"original compression enable", "%d",
941 original_compression_enabled},
942 {"two stage encoding", "%d", two_stage_encoding},
943 {"low power mode", "%d", low_power},
944 {"DPB compression factor", DUMP_FP_FMT,
945 dpb_compression_factor},
946 {"original compression factor", DUMP_FP_FMT,
947 original_compression_factor},
948 {"rotation", "%d", rotation},
949 {"cropping or scaling", "%d", cropping_or_scaling},
950 {"VMEM size (KB)", "%d", vmem_size},
951
952 {"DERIVED PARAMETERS", "", DUMP_HEADER_MAGIC},
953 {"LCU size", "%d", lcu_size},
954 {"GOB pattern", "%d", gop},
955 {"bitrate (Mbit/sec)", "%lu", bitrate},
956 {"bins to bit factor", DUMP_FP_FMT, bins_to_bit_factor},
957 {"B-frames enabled", "%d", b_frames_enabled},
958 {"search window size vertical (B)", "%d",
959 search_window_size_vertical_b},
960 {"search window factor (B)", "%d", search_window_factor_b},
961 {"search window factor BW (B)", "%d",
962 search_window_factor_bw_b},
963 {"VMEM size (B)", "%d", vmem_size_b},
964 {"bw increase (MB/s) (B)", DUMP_FP_FMT, bw_increase_b},
965 {"available VMEM (B)", "%d", available_vmem_b},
966 {"search window size vertical (P)", "%d",
967 search_window_size_vertical_p},
968 {"search window factor (P)", "%d", search_window_factor_p},
969 {"search window factor BW (P)", "%d",
970 search_window_factor_bw_p},
971 {"VMEM size (P)", "%d", vmem_size_p},
972 {"bw increase (MB/s) (P)", DUMP_FP_FMT, bw_increase_p},
973 {"available VMEM (P)", "%d", available_vmem_p},
974 {"chroma/luma factor DPB", DUMP_FP_FMT,
975 chroma_luma_factor_dpb},
976 {"one frame BW DPB (MB/s)", DUMP_FP_FMT, one_frame_bw_dpb},
977 {"chroma/Luma factor original", DUMP_FP_FMT,
978 chroma_luma_factor_original},
979 {"one frame BW original (MB/s)", DUMP_FP_FMT,
980 one_frame_bw_original},
981 {"line buffer size per LCU", DUMP_FP_FMT,
982 line_buffer_size_per_lcu},
983 {"line buffer size (KB)", DUMP_FP_FMT, line_buffer_size},
984 {"line buffer BW (MB/s)", DUMP_FP_FMT, line_buffer_bw},
985 {"collocated MVs per LCU", "%d", collocated_mv_per_lcu},
986 {"original VMEM requirement (KB)", DUMP_FP_FMT,
987 original_vmem_requirement},
988
989 {"INTERMEDIATE B/W DDR", "", DUMP_HEADER_MAGIC},
990 {"VSP read", DUMP_FP_FMT, ddr.vsp_read},
991 {"VSP read", DUMP_FP_FMT, ddr.vsp_write},
992 {"collocated read", DUMP_FP_FMT, ddr.collocated_read},
993 {"collocated read", DUMP_FP_FMT, ddr.collocated_write},
994 {"line buffer read", DUMP_FP_FMT, ddr.line_buffer_read},
995 {"line buffer read", DUMP_FP_FMT, ddr.line_buffer_write},
996 {"original read", DUMP_FP_FMT, ddr.original_read},
997 {"original read", DUMP_FP_FMT, ddr.original_write},
998 {"DPB read", DUMP_FP_FMT, ddr.dpb_read},
999 {"DPB write", DUMP_FP_FMT, ddr.dpb_write},
1000
1001 {"INTERMEDIATE B/W VMEM", "", DUMP_HEADER_MAGIC},
1002 {"VSP read", DUMP_FP_FMT, vmem.vsp_read},
1003 {"VSP read", DUMP_FP_FMT, vmem.vsp_write},
1004 {"collocated read", DUMP_FP_FMT, vmem.collocated_read},
1005 {"collocated read", DUMP_FP_FMT, vmem.collocated_write},
1006 {"line buffer read", DUMP_FP_FMT, vmem.line_buffer_read},
1007 {"line buffer read", DUMP_FP_FMT, vmem.line_buffer_write},
1008 {"original read", DUMP_FP_FMT, vmem.original_read},
1009 {"original read", DUMP_FP_FMT, vmem.original_write},
1010 {"DPB read", DUMP_FP_FMT, vmem.dpb_read},
1011 {"DPB write", DUMP_FP_FMT, vmem.dpb_write},
1012 };
1013 __dump(dump, ARRAY_SIZE(dump));
1014 }
1015
1016 switch (gm) {
1017 case GOVERNOR_DDR:
1018 ret = kbps(fp_round(ddr.total));
1019 break;
1020 case GOVERNOR_VMEM:
1021 ret = kbps(fp_round(vmem.total));
1022 break;
1023 case GOVERNOR_VMEM_PLUS:
1024 ret = __calculate_vmem_plus_ab(d);
1025 break;
1026 default:
1027 dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
1028 }
1029
1030 return ret;
1031}
1032
1033static unsigned long __calculate(struct vidc_bus_vote_data *d,
1034 enum governor_mode gm)
1035{
1036 unsigned long (*calc[])(struct vidc_bus_vote_data *,
1037 enum governor_mode) = {
1038 [HAL_VIDEO_DOMAIN_VPE] = __calculate_vpe,
1039 [HAL_VIDEO_DOMAIN_ENCODER] = __calculate_encoder,
1040 [HAL_VIDEO_DOMAIN_DECODER] = __calculate_decoder,
1041 };
1042
1043 return calc[d->domain](d, gm);
1044}
1045
1046static int __get_target_freq(struct devfreq *dev, unsigned long *freq)
1047{
1048 unsigned long ab_kbps = 0, c = 0;
1049 struct devfreq_dev_status stats = {0};
1050 struct msm_vidc_gov_data *vidc_data = NULL;
1051 struct governor *gov = NULL;
1052
1053 if (!dev || !freq)
1054 return -EINVAL;
1055
1056 gov = container_of(dev->governor,
1057 struct governor, devfreq_gov);
1058 dev->profile->get_dev_status(dev->dev.parent, &stats);
1059 vidc_data = (struct msm_vidc_gov_data *)stats.private_data;
1060
1061 for (c = 0; c < vidc_data->data_count; ++c) {
1062 if (vidc_data->data->power_mode == VIDC_POWER_TURBO) {
1063 *freq = INT_MAX;
1064 goto exit;
1065 }
1066 }
1067
1068 for (c = 0; c < vidc_data->data_count; ++c)
1069 ab_kbps += __calculate(&vidc_data->data[c], gov->mode);
1070
1071 *freq = clamp(ab_kbps, dev->min_freq, dev->max_freq ?: UINT_MAX);
1072exit:
1073 return 0;
1074}
1075
1076static int __event_handler(struct devfreq *devfreq, unsigned int event,
1077 void *data)
1078{
1079 int rc = 0;
1080
1081 if (!devfreq)
1082 return -EINVAL;
1083
1084 switch (event) {
1085 case DEVFREQ_GOV_START:
1086 case DEVFREQ_GOV_RESUME:
1087 mutex_lock(&devfreq->lock);
1088 rc = update_devfreq(devfreq);
1089 mutex_unlock(&devfreq->lock);
1090 break;
1091 }
1092
1093 return rc;
1094}
1095
1096static struct governor governors[] = {
1097 {
1098 .mode = GOVERNOR_DDR,
1099 .devfreq_gov = {
1100 .name = "msm-vidc-ddr",
1101 .get_target_freq = __get_target_freq,
1102 .event_handler = __event_handler,
1103 },
1104 },
1105 {
1106 .mode = GOVERNOR_VMEM,
1107 .devfreq_gov = {
1108 .name = "msm-vidc-vmem",
1109 .get_target_freq = __get_target_freq,
1110 .event_handler = __event_handler,
1111 },
1112 },
1113 {
1114 .mode = GOVERNOR_VMEM_PLUS,
1115 .devfreq_gov = {
1116 .name = "msm-vidc-vmem+",
1117 .get_target_freq = __get_target_freq,
1118 .event_handler = __event_handler,
1119 },
1120 },
1121};
1122
1123static int __init msm_vidc_bw_gov_init(void)
1124{
1125 int c = 0, rc = 0;
1126
1127 for (c = 0; c < ARRAY_SIZE(governors); ++c) {
1128 dprintk(VIDC_DBG, "Adding governor %s\n",
1129 governors[c].devfreq_gov.name);
1130
1131 rc = devfreq_add_governor(&governors[c].devfreq_gov);
1132 if (rc) {
1133 dprintk(VIDC_ERR, "Error adding governor %s: %d\n",
1134 governors[c].devfreq_gov.name, rc);
1135 break;
1136 }
1137 }
1138
1139 return rc;
1140}
1141module_init(msm_vidc_bw_gov_init);
1142
1143static void __exit msm_vidc_bw_gov_exit(void)
1144{
1145 int c = 0;
1146
1147 for (c = 0; c < ARRAY_SIZE(governors); ++c) {
1148 dprintk(VIDC_DBG, "Removing governor %s\n",
1149 governors[c].devfreq_gov.name);
1150 devfreq_remove_governor(&governors[c].devfreq_gov);
1151 }
1152}
1153module_exit(msm_vidc_bw_gov_exit);
1154MODULE_LICENSE("GPL v2");