@@ -210,6 +210,9 @@ static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = {
210210 */
211211#define SCARLETT2_MUX_MAX 77
212212
213+ /* Maximum number of sources (sum of input port counts) */
214+ #define SCARLETT2_MAX_SRCS 52
215+
213216/* Maximum number of meters (sum of output port counts) */
214217#define SCARLETT2_MAX_METERS 65
215218
@@ -328,6 +331,18 @@ struct scarlett2_mux_entry {
328331 u8 count ;
329332};
330333
334+ /* Maximum number of entries in a mux table */
335+ #define SCARLETT2_MAX_METER_ENTRIES 9
336+
337+ /* One entry within meter_assignment defines the range of mux outputs
338+ * that consecutive meter entries are mapped to. The end of the list
339+ * is marked with count == 0.
340+ */
341+ struct scarlett2_meter_entry {
342+ u8 start ;
343+ u8 count ;
344+ };
345+
331346struct scarlett2_device_info {
332347 /* Gen 3 devices have an internal MSD mode switch that needs
333348 * to be disabled in order to access the full functionality of
@@ -381,6 +396,7 @@ struct scarlett2_device_info {
381396 */
382397 u8 line_out_remap_enable ;
383398 u8 line_out_remap [SCARLETT2_ANALOGUE_MAX ];
399+ u8 line_out_unmap [SCARLETT2_ANALOGUE_MAX ];
384400
385401 /* additional description for the line out volume controls */
386402 const char * const line_out_descrs [SCARLETT2_ANALOGUE_MAX ];
@@ -391,6 +407,12 @@ struct scarlett2_device_info {
391407 /* layout/order of the entries in the set_mux message */
392408 struct scarlett2_mux_entry mux_assignment [SCARLETT2_MUX_TABLES ]
393409 [SCARLETT2_MAX_MUX_ENTRIES ];
410+
411+ /* map from meter level order returned by
412+ * SCARLETT2_USB_GET_METER to index into mux[] entries (same
413+ * as the order returned by scarlett2_meter_ctl_get())
414+ */
415+ struct scarlett2_meter_entry meter_map [SCARLETT2_MAX_METER_ENTRIES ];
394416};
395417
396418struct scarlett2_data {
@@ -431,6 +453,7 @@ struct scarlett2_data {
431453 u8 talkback_map [SCARLETT2_OUTPUT_MIX_MAX ];
432454 u8 msd_switch ;
433455 u8 standalone_switch ;
456+ u8 meter_level_map [SCARLETT2_MAX_METERS ];
434457 struct snd_kcontrol * sync_ctl ;
435458 struct snd_kcontrol * master_vol_ctl ;
436459 struct snd_kcontrol * vol_ctls [SCARLETT2_ANALOGUE_MAX ];
@@ -493,6 +516,12 @@ static const struct scarlett2_device_info s6i6_gen2_info = {
493516 { SCARLETT2_PORT_TYPE_NONE , 0 , 8 },
494517 { 0 , 0 , 0 },
495518 } },
519+
520+ .meter_map = {
521+ { 24 , 6 },
522+ { 0 , 24 },
523+ { 0 , 0 },
524+ }
496525};
497526
498527static const struct scarlett2_device_info s18i8_gen2_info = {
@@ -540,6 +569,12 @@ static const struct scarlett2_device_info s18i8_gen2_info = {
540569 { SCARLETT2_PORT_TYPE_NONE , 0 , 4 },
541570 { 0 , 0 , 0 },
542571 } },
572+
573+ .meter_map = {
574+ { 26 , 18 },
575+ { 0 , 26 },
576+ { 0 , 0 },
577+ }
543578};
544579
545580static const struct scarlett2_device_info s18i20_gen2_info = {
@@ -592,6 +627,12 @@ static const struct scarlett2_device_info s18i20_gen2_info = {
592627 { SCARLETT2_PORT_TYPE_NONE , 0 , 6 },
593628 { 0 , 0 , 0 },
594629 } },
630+
631+ .meter_map = {
632+ { 38 , 18 },
633+ { 0 , 38 },
634+ { 0 , 0 },
635+ }
595636};
596637
597638static const struct scarlett2_device_info solo_gen3_info = {
@@ -657,6 +698,12 @@ static const struct scarlett2_device_info s4i4_gen3_info = {
657698 { SCARLETT2_PORT_TYPE_NONE , 0 , 16 },
658699 { 0 , 0 , 0 },
659700 } },
701+
702+ .meter_map = {
703+ { 12 , 6 },
704+ { 0 , 12 },
705+ { 0 , 0 },
706+ }
660707};
661708
662709static const struct scarlett2_device_info s8i6_gen3_info = {
@@ -708,6 +755,14 @@ static const struct scarlett2_device_info s8i6_gen3_info = {
708755 { SCARLETT2_PORT_TYPE_NONE , 0 , 18 },
709756 { 0 , 0 , 0 },
710757 } },
758+
759+ .meter_map = {
760+ { 14 , 8 },
761+ { 0 , 6 },
762+ { 22 , 2 },
763+ { 6 , 8 },
764+ { 0 , 0 },
765+ }
711766};
712767
713768static const struct scarlett2_device_info s18i8_gen3_info = {
@@ -723,6 +778,7 @@ static const struct scarlett2_device_info s18i8_gen3_info = {
723778
724779 .line_out_remap_enable = 1 ,
725780 .line_out_remap = { 0 , 1 , 6 , 7 , 2 , 3 , 4 , 5 },
781+ .line_out_unmap = { 0 , 1 , 4 , 5 , 6 , 7 , 2 , 3 },
726782
727783 .line_out_descrs = {
728784 "Monitor L" ,
@@ -776,6 +832,18 @@ static const struct scarlett2_device_info s18i8_gen3_info = {
776832 { SCARLETT2_PORT_TYPE_NONE , 0 , 10 },
777833 { 0 , 0 , 0 },
778834 } },
835+
836+ .meter_map = {
837+ { 30 , 10 },
838+ { 42 , 8 },
839+ { 0 , 2 },
840+ { 6 , 2 },
841+ { 2 , 4 },
842+ { 8 , 2 },
843+ { 40 , 2 },
844+ { 10 , 20 },
845+ { 0 , 0 }
846+ }
779847};
780848
781849static const struct scarlett2_device_info s18i20_gen3_info = {
@@ -839,6 +907,15 @@ static const struct scarlett2_device_info s18i20_gen3_info = {
839907 { SCARLETT2_PORT_TYPE_NONE , 0 , 24 },
840908 { 0 , 0 , 0 },
841909 } },
910+
911+ .meter_map = {
912+ { 45 , 8 },
913+ { 55 , 10 },
914+ { 0 , 20 },
915+ { 53 , 2 },
916+ { 20 , 25 },
917+ { 0 , 0 },
918+ }
842919};
843920
844921static const struct scarlett2_device_info clarett_2pre_info = {
@@ -881,6 +958,12 @@ static const struct scarlett2_device_info clarett_2pre_info = {
881958 { SCARLETT2_PORT_TYPE_NONE , 0 , 26 },
882959 { 0 , 0 , 0 },
883960 } },
961+
962+ .meter_map = {
963+ { 22 , 12 },
964+ { 0 , 22 },
965+ { 0 , 0 }
966+ }
884967};
885968
886969static const struct scarlett2_device_info clarett_4pre_info = {
@@ -928,6 +1011,12 @@ static const struct scarlett2_device_info clarett_4pre_info = {
9281011 { SCARLETT2_PORT_TYPE_NONE , 0 , 24 },
9291012 { 0 , 0 , 0 },
9301013 } },
1014+
1015+ .meter_map = {
1016+ { 26 , 18 },
1017+ { 0 , 26 },
1018+ { 0 , 0 }
1019+ }
9311020};
9321021
9331022static const struct scarlett2_device_info clarett_8pre_info = {
@@ -981,6 +1070,12 @@ static const struct scarlett2_device_info clarett_8pre_info = {
9811070 { SCARLETT2_PORT_TYPE_NONE , 0 , 22 },
9821071 { 0 , 0 , 0 },
9831072 } },
1073+
1074+ .meter_map = {
1075+ { 38 , 18 },
1076+ { 0 , 38 },
1077+ { 0 , 0 }
1078+ }
9841079};
9851080
9861081struct scarlett2_device_entry {
@@ -1688,6 +1783,79 @@ static void scarlett2_usb_populate_mux(struct scarlett2_data *private,
16881783 private -> mux [dst_idx ] = src_idx ;
16891784}
16901785
1786+ /* Update the meter level map
1787+ *
1788+ * The meter level data from the interface (SCARLETT2_USB_GET_METER
1789+ * request) is returned in mux_assignment order, but to avoid exposing
1790+ * that to userspace, scarlett2_meter_ctl_get() rearranges the data
1791+ * into scarlett2_ports order using the meter_level_map[] array which
1792+ * is set up by this function.
1793+ *
1794+ * In addition, the meter level data values returned from the
1795+ * interface are invalid for destinations where:
1796+ *
1797+ * - the source is "Off"; therefore we set those values to zero (map
1798+ * value of 255)
1799+ *
1800+ * - the source is assigned to a previous (with respect to the
1801+ * mux_assignment order) destination; therefore we set those values
1802+ * to the value previously reported for that source
1803+ */
1804+ static void scarlett2_update_meter_level_map (struct scarlett2_data * private )
1805+ {
1806+ const struct scarlett2_device_info * info = private -> info ;
1807+ const int (* port_count )[SCARLETT2_PORT_DIRNS ] = info -> port_count ;
1808+ int line_out_count =
1809+ port_count [SCARLETT2_PORT_TYPE_ANALOGUE ][SCARLETT2_PORT_OUT ];
1810+ const struct scarlett2_meter_entry * entry ;
1811+
1812+ /* sources already assigned to a destination
1813+ * value is 255 for None, otherwise the value of i
1814+ * (index into array returned by
1815+ * scarlett2_usb_get_meter_levels())
1816+ */
1817+ u8 seen_src [SCARLETT2_MAX_SRCS ] = { 1 };
1818+ u8 seen_src_value [SCARLETT2_MAX_SRCS ] = { 255 };
1819+
1820+ /* index in meter_map[] order */
1821+ int i = 0 ;
1822+
1823+ /* go through the meter_map[] entries */
1824+ for (entry = info -> meter_map ;
1825+ entry -> count ;
1826+ entry ++ ) {
1827+
1828+ /* fill in each meter_level_map[] entry */
1829+ int j , mux_idx ;
1830+
1831+ for (j = 0 , mux_idx = entry -> start ;
1832+ j < entry -> count ;
1833+ i ++ , j ++ , mux_idx ++ ) {
1834+
1835+ /* convert mux_idx using line_out_unmap[] */
1836+ int map_mux_idx = (
1837+ info -> line_out_remap_enable &&
1838+ mux_idx < line_out_count
1839+ ) ? info -> line_out_unmap [mux_idx ]
1840+ : mux_idx ;
1841+
1842+ /* check which source is connected, and if
1843+ * that source is already connected elsewhere,
1844+ * use that existing connection's destination
1845+ * for this meter entry instead
1846+ */
1847+ int mux_src = private -> mux [mux_idx ];
1848+
1849+ if (!seen_src [mux_src ]) {
1850+ seen_src [mux_src ] = 1 ;
1851+ seen_src_value [mux_src ] = i ;
1852+ }
1853+ private -> meter_level_map [map_mux_idx ] =
1854+ seen_src_value [mux_src ];
1855+ }
1856+ }
1857+ }
1858+
16911859/* Send USB message to get mux inputs and then populate private->mux[] */
16921860static int scarlett2_usb_get_mux (struct usb_mixer_interface * mixer )
16931861{
@@ -1716,6 +1884,8 @@ static int scarlett2_usb_get_mux(struct usb_mixer_interface *mixer)
17161884 for (i = 0 ; i < count ; i ++ )
17171885 scarlett2_usb_populate_mux (private , le32_to_cpu (data [i ]));
17181886
1887+ scarlett2_update_meter_level_map (private );
1888+
17191889 return 0 ;
17201890}
17211891
@@ -1782,6 +1952,8 @@ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer)
17821952 return err ;
17831953 }
17841954
1955+ scarlett2_update_meter_level_map (private );
1956+
17851957 return 0 ;
17861958}
17871959
@@ -3619,6 +3791,8 @@ static int scarlett2_meter_ctl_get(struct snd_kcontrol *kctl,
36193791 struct snd_ctl_elem_value * ucontrol )
36203792{
36213793 struct usb_mixer_elem_info * elem = kctl -> private_data ;
3794+ struct scarlett2_data * private = elem -> head .mixer -> private_data ;
3795+ u8 * meter_level_map = private -> meter_level_map ;
36223796 u16 meter_levels [SCARLETT2_MAX_METERS ];
36233797 int i , err ;
36243798
@@ -3627,8 +3801,18 @@ static int scarlett2_meter_ctl_get(struct snd_kcontrol *kctl,
36273801 if (err < 0 )
36283802 return err ;
36293803
3630- for (i = 0 ; i < elem -> channels ; i ++ )
3631- ucontrol -> value .integer .value [i ] = meter_levels [i ];
3804+ /* copy & translate from meter_levels[] using meter_level_map[] */
3805+ for (i = 0 ; i < elem -> channels ; i ++ ) {
3806+ int idx = meter_level_map [i ];
3807+ int value ;
3808+
3809+ if (idx == 255 )
3810+ value = 0 ;
3811+ else
3812+ value = meter_levels [idx ];
3813+
3814+ ucontrol -> value .integer .value [i ] = value ;
3815+ }
36323816
36333817 return 0 ;
36343818}
0 commit comments