diff options
author | Thomas Niederprüm <niederp@physik.uni-kl.de> | 2015-01-21 18:01:58 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-01-27 12:13:25 -0500 |
commit | f04b1e760a51120f358826d815d12c3f8ecdf1b4 (patch) | |
tree | 15ab3cf75b2dd1d2622c0874532890514e418d05 | |
parent | 1c34c876c4abb219381dcb7096206f1a609f119b (diff) |
ASoC: sta32x: add device tree binding.
make the sta32x driver usable with device tree configs. Code is heavily based
on the sta350 driver.
Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | Documentation/devicetree/bindings/sound/st,sta32x.txt | 92 | ||||
-rw-r--r-- | include/sound/sta32x.h | 18 | ||||
-rw-r--r-- | sound/soc/codecs/sta32x.c | 108 |
3 files changed, 211 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/sound/st,sta32x.txt b/Documentation/devicetree/bindings/sound/st,sta32x.txt new file mode 100644 index 000000000000..255de3ae5b2f --- /dev/null +++ b/Documentation/devicetree/bindings/sound/st,sta32x.txt | |||
@@ -0,0 +1,92 @@ | |||
1 | STA32X audio CODEC | ||
2 | |||
3 | The driver for this device only supports I2C. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible: "st,sta32x" | ||
8 | - reg: the I2C address of the device for I2C | ||
9 | - reset-gpios: a GPIO spec for the reset pin. If specified, it will be | ||
10 | deasserted before communication to the codec starts. | ||
11 | |||
12 | - power-down-gpios: a GPIO spec for the power down pin. If specified, | ||
13 | it will be deasserted before communication to the codec | ||
14 | starts. | ||
15 | |||
16 | - Vdda-supply: regulator spec, providing 3.3V | ||
17 | - Vdd3-supply: regulator spec, providing 3.3V | ||
18 | - Vcc-supply: regulator spec, providing 5V - 26V | ||
19 | |||
20 | Optional properties: | ||
21 | |||
22 | - st,output-conf: number, Selects the output configuration: | ||
23 | 0: 2-channel (full-bridge) power, 2-channel data-out | ||
24 | 1: 2 (half-bridge). 1 (full-bridge) on-board power | ||
25 | 2: 2 Channel (Full-Bridge) Power, 1 Channel FFX | ||
26 | 3: 1 Channel Mono-Parallel | ||
27 | If parameter is missing, mode 0 will be enabled. | ||
28 | This property has to be specified as '/bits/ 8' value. | ||
29 | |||
30 | - st,ch1-output-mapping: Channel 1 output mapping | ||
31 | - st,ch2-output-mapping: Channel 2 output mapping | ||
32 | - st,ch3-output-mapping: Channel 3 output mapping | ||
33 | 0: Channel 1 | ||
34 | 1: Channel 2 | ||
35 | 2: Channel 3 | ||
36 | If parameter is missing, channel 1 is chosen. | ||
37 | This properties have to be specified as '/bits/ 8' values. | ||
38 | |||
39 | - st,thermal-warning-recover: | ||
40 | If present, thermal warning recovery is enabled. | ||
41 | |||
42 | - st,thermal-warning-adjustment: | ||
43 | If present, thermal warning adjustment is enabled. | ||
44 | |||
45 | - st,fault-detect-recovery: | ||
46 | If present, then fault recovery will be enabled. | ||
47 | |||
48 | - st,drop-compensation-ns: number | ||
49 | Only required for "st,ffx-power-output-mode" == | ||
50 | "variable-drop-compensation". | ||
51 | Specifies the drop compensation in nanoseconds. | ||
52 | The value must be in the range of 0..300, and only | ||
53 | multiples of 20 are allowed. Default is 140ns. | ||
54 | |||
55 | - st,max-power-use-mpcc: | ||
56 | If present, then MPCC bits are used for MPC coefficients, | ||
57 | otherwise standard MPC coefficients are used. | ||
58 | |||
59 | - st,max-power-corr: | ||
60 | If present, power bridge correction for THD reduction near maximum | ||
61 | power output is enabled. | ||
62 | |||
63 | - st,am-reduction-mode: | ||
64 | If present, FFX mode runs in AM reduction mode, otherwise normal | ||
65 | FFX mode is used. | ||
66 | |||
67 | - st,odd-pwm-speed-mode: | ||
68 | If present, PWM speed mode run on odd speed mode (341.3 kHz) on all | ||
69 | channels. If not present, normal PWM spped mode (384 kHz) will be used. | ||
70 | |||
71 | - st,invalid-input-detect-mute: | ||
72 | If present, automatic invalid input detect mute is enabled. | ||
73 | |||
74 | Example: | ||
75 | |||
76 | codec: sta32x@38 { | ||
77 | compatible = "st,sta32x"; | ||
78 | reg = <0x1c>; | ||
79 | reset-gpios = <&gpio1 19 0>; | ||
80 | power-down-gpios = <&gpio1 16 0>; | ||
81 | st,output-conf = /bits/ 8 <0x3>; // set output to 2-channel | ||
82 | // (full-bridge) power, | ||
83 | // 2-channel data-out | ||
84 | st,ch1-output-mapping = /bits/ 8 <0>; // set channel 1 output ch 1 | ||
85 | st,ch2-output-mapping = /bits/ 8 <0>; // set channel 2 output ch 1 | ||
86 | st,ch3-output-mapping = /bits/ 8 <0>; // set channel 3 output ch 1 | ||
87 | st,max-power-correction; // enables power bridge | ||
88 | // correction for THD reduction | ||
89 | // near maximum power output | ||
90 | st,invalid-input-detect-mute; // mute if no valid digital | ||
91 | // audio signal is provided. | ||
92 | }; | ||
diff --git a/include/sound/sta32x.h b/include/sound/sta32x.h index 8d93b0357a14..a894f7d17b1a 100644 --- a/include/sound/sta32x.h +++ b/include/sound/sta32x.h | |||
@@ -24,12 +24,20 @@ | |||
24 | #define STA32X_THERMAL_RECOVERY_ENABLE 2 | 24 | #define STA32X_THERMAL_RECOVERY_ENABLE 2 |
25 | 25 | ||
26 | struct sta32x_platform_data { | 26 | struct sta32x_platform_data { |
27 | int output_conf; | 27 | u8 output_conf; |
28 | int ch1_output_mapping; | 28 | u8 ch1_output_mapping; |
29 | int ch2_output_mapping; | 29 | u8 ch2_output_mapping; |
30 | int ch3_output_mapping; | 30 | u8 ch3_output_mapping; |
31 | int thermal_conf; | ||
32 | int needs_esd_watchdog; | 31 | int needs_esd_watchdog; |
32 | u8 drop_compensation_ns; | ||
33 | unsigned int thermal_warning_recovery:1; | ||
34 | unsigned int thermal_warning_adjustment:1; | ||
35 | unsigned int fault_detect_recovery:1; | ||
36 | unsigned int max_power_use_mpcc:1; | ||
37 | unsigned int max_power_correction:1; | ||
38 | unsigned int am_reduction_mode:1; | ||
39 | unsigned int odd_pwm_speed_mode:1; | ||
40 | unsigned int invalid_input_detect_mute:1; | ||
33 | }; | 41 | }; |
34 | 42 | ||
35 | #endif /* __LINUX_SND__STA32X_H */ | 43 | #endif /* __LINUX_SND__STA32X_H */ |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index ec2372498c92..669b67f8cee3 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include <linux/of_device.h> | ||
28 | #include <linux/of_gpio.h> | ||
27 | #include <linux/regmap.h> | 29 | #include <linux/regmap.h> |
28 | #include <linux/regulator/consumer.h> | 30 | #include <linux/regulator/consumer.h> |
29 | #include <linux/gpio/consumer.h> | 31 | #include <linux/gpio/consumer.h> |
@@ -893,15 +895,49 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
893 | dev_err(codec->dev, "Failed to startup device\n"); | 895 | dev_err(codec->dev, "Failed to startup device\n"); |
894 | return ret; | 896 | return ret; |
895 | } | 897 | } |
896 | /* set thermal warning adjustment and recovery */ | 898 | |
899 | /* CONFA */ | ||
897 | if (!pdata->thermal_warning_recovery) | 900 | if (!pdata->thermal_warning_recovery) |
898 | thermal |= STA32X_CONFA_TWAB; | 901 | thermal |= STA32X_CONFA_TWAB; |
899 | if (!pdata->thermal_warning_adjustment) | 902 | if (!pdata->thermal_warning_adjustment) |
900 | thermal |= STA32X_CONFA_TWRB; | 903 | thermal |= STA32X_CONFA_TWRB; |
904 | if (!pdata->fault_detect_recovery) | ||
905 | thermal |= STA32X_CONFA_FDRB; | ||
901 | regmap_update_bits(sta32x->regmap, STA32X_CONFA, | 906 | regmap_update_bits(sta32x->regmap, STA32X_CONFA, |
902 | STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, | 907 | STA32X_CONFA_TWAB | STA32X_CONFA_TWRB | |
908 | STA32X_CONFA_FDRB, | ||
903 | thermal); | 909 | thermal); |
904 | 910 | ||
911 | /* CONFC */ | ||
912 | regmap_update_bits(sta32x->regmap, STA32X_CONFC, | ||
913 | STA32X_CONFC_CSZ_MASK, | ||
914 | pdata->drop_compensation_ns | ||
915 | << STA32X_CONFC_CSZ_SHIFT); | ||
916 | |||
917 | /* CONFE */ | ||
918 | regmap_update_bits(sta32x->regmap, STA32X_CONFE, | ||
919 | STA32X_CONFE_MPCV, | ||
920 | pdata->max_power_use_mpcc ? | ||
921 | STA32X_CONFE_MPCV : 0); | ||
922 | regmap_update_bits(sta32x->regmap, STA32X_CONFE, | ||
923 | STA32X_CONFE_MPC, | ||
924 | pdata->max_power_correction ? | ||
925 | STA32X_CONFE_MPC : 0); | ||
926 | regmap_update_bits(sta32x->regmap, STA32X_CONFE, | ||
927 | STA32X_CONFE_AME, | ||
928 | pdata->am_reduction_mode ? | ||
929 | STA32X_CONFE_AME : 0); | ||
930 | regmap_update_bits(sta32x->regmap, STA32X_CONFE, | ||
931 | STA32X_CONFE_PWMS, | ||
932 | pdata->odd_pwm_speed_mode ? | ||
933 | STA32X_CONFE_PWMS : 0); | ||
934 | |||
935 | /* CONFF */ | ||
936 | regmap_update_bits(sta32x->regmap, STA32X_CONFF, | ||
937 | STA32X_CONFF_IDE, | ||
938 | pdata->invalid_input_detect_mute ? | ||
939 | STA32X_CONFF_IDE : 0); | ||
940 | |||
905 | /* select output configuration */ | 941 | /* select output configuration */ |
906 | regmap_update_bits(sta32x->regmap, STA32X_CONFF, | 942 | regmap_update_bits(sta32x->regmap, STA32X_CONFF, |
907 | STA32X_CONFF_OCFG_MASK, | 943 | STA32X_CONFF_OCFG_MASK, |
@@ -977,7 +1013,66 @@ static const struct regmap_config sta32x_regmap = { | |||
977 | .rd_table = &sta32x_read_regs, | 1013 | .rd_table = &sta32x_read_regs, |
978 | .volatile_table = &sta32x_volatile_regs, | 1014 | .volatile_table = &sta32x_volatile_regs, |
979 | }; | 1015 | }; |
1016 | |||
1017 | #ifdef CONFIG_OF | ||
1018 | static const struct of_device_id st32x_dt_ids[] = { | ||
1019 | { .compatible = "st,sta32x", }, | ||
1020 | { } | ||
980 | }; | 1021 | }; |
1022 | MODULE_DEVICE_TABLE(of, st32x_dt_ids); | ||
1023 | |||
1024 | static int sta32x_probe_dt(struct device *dev, struct sta32x_priv *sta32x) | ||
1025 | { | ||
1026 | struct device_node *np = dev->of_node; | ||
1027 | struct sta32x_platform_data *pdata; | ||
1028 | u16 tmp; | ||
1029 | |||
1030 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
1031 | if (!pdata) | ||
1032 | return -ENOMEM; | ||
1033 | |||
1034 | of_property_read_u8(np, "st,output-conf", | ||
1035 | &pdata->output_conf); | ||
1036 | of_property_read_u8(np, "st,ch1-output-mapping", | ||
1037 | &pdata->ch1_output_mapping); | ||
1038 | of_property_read_u8(np, "st,ch2-output-mapping", | ||
1039 | &pdata->ch2_output_mapping); | ||
1040 | of_property_read_u8(np, "st,ch3-output-mapping", | ||
1041 | &pdata->ch3_output_mapping); | ||
1042 | |||
1043 | if (of_get_property(np, "st,thermal-warning-recovery", NULL)) | ||
1044 | pdata->thermal_warning_recovery = 1; | ||
1045 | if (of_get_property(np, "st,thermal-warning-adjustment", NULL)) | ||
1046 | pdata->thermal_warning_adjustment = 1; | ||
1047 | if (of_get_property(np, "st,needs_esd_watchdog", NULL)) | ||
1048 | pdata->needs_esd_watchdog = 1; | ||
1049 | |||
1050 | tmp = 140; | ||
1051 | of_property_read_u16(np, "st,drop-compensation-ns", &tmp); | ||
1052 | pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20; | ||
1053 | |||
1054 | /* CONFE */ | ||
1055 | if (of_get_property(np, "st,max-power-use-mpcc", NULL)) | ||
1056 | pdata->max_power_use_mpcc = 1; | ||
1057 | |||
1058 | if (of_get_property(np, "st,max-power-correction", NULL)) | ||
1059 | pdata->max_power_correction = 1; | ||
1060 | |||
1061 | if (of_get_property(np, "st,am-reduction-mode", NULL)) | ||
1062 | pdata->am_reduction_mode = 1; | ||
1063 | |||
1064 | if (of_get_property(np, "st,odd-pwm-speed-mode", NULL)) | ||
1065 | pdata->odd_pwm_speed_mode = 1; | ||
1066 | |||
1067 | /* CONFF */ | ||
1068 | if (of_get_property(np, "st,invalid-input-detect-mute", NULL)) | ||
1069 | pdata->invalid_input_detect_mute = 1; | ||
1070 | |||
1071 | sta32x->pdata = pdata; | ||
1072 | |||
1073 | return 0; | ||
1074 | } | ||
1075 | #endif | ||
981 | 1076 | ||
982 | static int sta32x_i2c_probe(struct i2c_client *i2c, | 1077 | static int sta32x_i2c_probe(struct i2c_client *i2c, |
983 | const struct i2c_device_id *id) | 1078 | const struct i2c_device_id *id) |
@@ -994,6 +1089,14 @@ static int sta32x_i2c_probe(struct i2c_client *i2c, | |||
994 | mutex_init(&sta32x->coeff_lock); | 1089 | mutex_init(&sta32x->coeff_lock); |
995 | sta32x->pdata = dev_get_platdata(dev); | 1090 | sta32x->pdata = dev_get_platdata(dev); |
996 | 1091 | ||
1092 | #ifdef CONFIG_OF | ||
1093 | if (dev->of_node) { | ||
1094 | ret = sta32x_probe_dt(dev, sta32x); | ||
1095 | if (ret < 0) | ||
1096 | return ret; | ||
1097 | } | ||
1098 | #endif | ||
1099 | |||
997 | /* GPIOs */ | 1100 | /* GPIOs */ |
998 | sta32x->gpiod_nreset = devm_gpiod_get(dev, "reset"); | 1101 | sta32x->gpiod_nreset = devm_gpiod_get(dev, "reset"); |
999 | if (IS_ERR(sta32x->gpiod_nreset)) { | 1102 | if (IS_ERR(sta32x->gpiod_nreset)) { |
@@ -1051,6 +1154,7 @@ static struct i2c_driver sta32x_i2c_driver = { | |||
1051 | .driver = { | 1154 | .driver = { |
1052 | .name = "sta32x", | 1155 | .name = "sta32x", |
1053 | .owner = THIS_MODULE, | 1156 | .owner = THIS_MODULE, |
1157 | .of_match_table = of_match_ptr(st32x_dt_ids), | ||
1054 | }, | 1158 | }, |
1055 | .probe = sta32x_i2c_probe, | 1159 | .probe = sta32x_i2c_probe, |
1056 | .remove = sta32x_i2c_remove, | 1160 | .remove = sta32x_i2c_remove, |