1313
1414#include "cmucal.h"
1515#include "fvmap.h"
16+ #include "gpu_dvfs_overrides.h"
1617#include "ra.h"
1718#include "vclk.h"
1819
@@ -26,6 +27,37 @@ static int init_margin_table[MAX_MARGIN_ID];
2627static int volt_offset_percent = 0 ;
2728static int percent_margin_table [MAX_MARGIN_ID ];
2829
30+ #define G3D_MANUAL_RATE (_mhz , _uv ) {.rate = (_mhz) * 1000U, .volt = (_uv)}
31+
32+ static const struct rate_volt g3d_manual_ratevolt [] = {
33+ G3D_MANUAL_RATE (754 , 800000 ),
34+ G3D_MANUAL_RATE (702 , 775000 ),
35+ G3D_MANUAL_RATE (650 , 750000 ),
36+ G3D_MANUAL_RATE (572 , 725000 ),
37+ G3D_MANUAL_RATE (433 , 700000 ),
38+ G3D_MANUAL_RATE (377 , 675000 ),
39+ G3D_MANUAL_RATE (325 , 650000 ),
40+ G3D_MANUAL_RATE (260 , 625000 ),
41+ G3D_MANUAL_RATE (200 , 600000 ),
42+ G3D_MANUAL_RATE (156 , 575000 ),
43+ G3D_MANUAL_RATE (100 , 550000 ),
44+ };
45+
46+ static size_t
47+ fvmap_ratevolt_capacity (const volatile struct fvmap_header * header ) {
48+ size_t capacity = header -> num_of_lv ;
49+
50+ if (header -> o_tables > header -> o_ratevolt ) {
51+ size_t ratevolt_capacity =
52+ (header -> o_tables - header -> o_ratevolt ) / sizeof (struct rate_volt );
53+
54+ if (ratevolt_capacity && ratevolt_capacity < capacity )
55+ capacity = ratevolt_capacity ;
56+ }
57+
58+ return capacity ;
59+ }
60+
2961static size_t
3062fvmap_calculate_initial_usage (const volatile struct fvmap_header * header ,
3163 int num_of_vclks ) {
@@ -50,6 +82,35 @@ fvmap_calculate_initial_usage(const volatile struct fvmap_header *header,
5082 return ALIGN (max_offset , sizeof (u32 ));
5183}
5284
85+ static void fvmap_apply_gpu_manual_table (volatile struct fvmap_header * header ,
86+ struct rate_volt_header * rate_table ,
87+ struct vclk * vclk ) {
88+ size_t manual_count = ARRAY_SIZE (g3d_manual_ratevolt );
89+ size_t capacity = fvmap_ratevolt_capacity (header );
90+ size_t idx ;
91+
92+ if (capacity < manual_count ) {
93+ pr_warn (" G3D manual table truncated to %zu entries (capacity %zu)\n" ,
94+ capacity , manual_count );
95+ manual_count = capacity ;
96+ }
97+
98+ if (!manual_count )
99+ return ;
100+
101+ memcpy (rate_table -> table , g3d_manual_ratevolt ,
102+ manual_count * sizeof (struct rate_volt ));
103+ header -> num_of_lv = manual_count ;
104+
105+ if (vclk && vclk -> lut && vclk -> num_rates < manual_count )
106+ vclk -> num_rates = manual_count ;
107+
108+ if (vclk && vclk -> lut ) {
109+ for (idx = 0 ; idx < manual_count && idx < vclk -> num_rates ; idx ++ )
110+ vclk -> lut [idx ].rate = g3d_manual_ratevolt [idx ].rate ;
111+ }
112+ }
113+
53114static int __init get_mif_volt (char * str ) {
54115 int volt ;
55116
@@ -451,11 +512,60 @@ static void fvmap_copy_from_sram(void __iomem *map_base,
451512
452513 fw_lv = header [i ].num_of_lv ;
453514
515+ if (!strcmp (vclk -> name , "dvfs_g3d" )) {
516+ size_t manual_lv = ARRAY_SIZE (g3d_manual_ratevolt );
517+ size_t capacity = fvmap_ratevolt_capacity (& header [i ]);
518+
519+ if (manual_lv > capacity ) {
520+ size_t ratevolt_bytes = manual_lv * sizeof (struct rate_volt );
521+ size_t table_bytes = manual_lv * fvmap_header [i ].num_of_members ;
522+ size_t new_ratevolt_offset =
523+ ALIGN (next_free_offset , sizeof (struct rate_volt ));
524+ size_t new_tables_offset =
525+ ALIGN (new_ratevolt_offset + ratevolt_bytes , sizeof (u32 ));
526+ size_t new_end = new_tables_offset + table_bytes ;
527+
528+ if (new_end > FVMAP_SIZE ) {
529+ pr_err (" G3D: unable to extend manual table, "
530+ "need %zu bytes, limit %lu – truncating\n" ,
531+ new_end , FVMAP_SIZE );
532+ manual_lv = capacity ;
533+ } else {
534+ pr_info (" G3D: relocating rate/volt tables to 0x%zx "
535+ "to fit %zu entries\n" ,
536+ new_ratevolt_offset , manual_lv );
537+ fvmap_header [i ].o_ratevolt = new_ratevolt_offset ;
538+ fvmap_header [i ].o_tables = new_tables_offset ;
539+ next_free_offset = new_end ;
540+ capacity = manual_lv ;
541+ }
542+ }
543+
544+ if (manual_lv > capacity ) {
545+ pr_warn (" G3D: manual table has %zu entries, "
546+ "FW/capacity only %zu – truncating!\n" ,
547+ manual_lv , capacity );
548+ manual_lv = capacity ;
549+ }
550+
551+ pr_info (" G3D: using %zu levels from manual table "
552+ "(FW advertised %u)\n" ,
553+ manual_lv , fw_lv );
554+
555+ fvmap_header [i ].num_of_lv = manual_lv ;
556+ }
557+
454558 pr_info ("dvfs_type : %s - id : %x\n" , vclk -> name ,
455559 fvmap_header [i ].dvfs_type );
456560 pr_info (" num_of_lv : %d\n" , fvmap_header [i ].num_of_lv );
457561 pr_info (" num_of_members : %d\n" , fvmap_header [i ].num_of_members );
458562
563+ if (!strcmp (vclk -> name , "dvfs_g3d" )) {
564+ pr_info (" G3D init level : %d\n" , fvmap_header [i ].init_lv );
565+ pr_info (" G3D volt_offset_percent : %d\n" , volt_offset_percent );
566+ pr_info (" Using manual G3D rate/volt table\n" );
567+ }
568+
459569 old = sram_base + header [i ].o_ratevolt ;
460570 new = map_base + fvmap_header [i ].o_ratevolt ;
461571
@@ -504,6 +614,10 @@ static void fvmap_copy_from_sram(void __iomem *map_base,
504614 new -> table [j ].volt , volt_offset_percent );
505615 }
506616
617+ if (!strcmp (vclk -> name , "dvfs_g3d" )) {
618+ fvmap_apply_gpu_manual_table (& fvmap_header [i ], new , vclk );
619+ }
620+
507621 for (j = 0 ; j < fvmap_header [i ].num_of_lv ; j ++ ) {
508622 pr_info (" lv : [%7d], volt = %d uV (%d %%) \n" , new -> table [j ].rate ,
509623 new -> table [j ].volt , volt_offset_percent );
@@ -526,6 +640,18 @@ static void fvmap_copy_from_sram(void __iomem *map_base,
526640 }
527641 }
528642
643+ if (!strcmp (vclk -> name , "dvfs_g3d" )) {
644+ size_t manual_lv = fvmap_header [i ].num_of_lv ;
645+
646+ if (manual_lv > fw_lv && fw_lv ) {
647+ size_t stride = fvmap_header [i ].num_of_members ;
648+
649+ for (j = fw_lv ; j < manual_lv ; j ++ ) {
650+ memcpy (& new_param -> val [stride * j ],
651+ & new_param -> val [stride * (fw_lv - 1 )], stride );
652+ }
653+ }
654+ }
529655 }
530656}
531657
0 commit comments