diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2013-04-08 16:27:18 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-04-14 18:55:22 -0400 |
commit | 03aa1bcd92eca82735e1de6d3e71bebf6e1c516e (patch) | |
tree | 2b3d56a9a63ab2e66352984f76fd3a0e6c5d6350 | |
parent | b387754d7256b1fa3610ed8a85f9274df49d1178 (diff) |
[media] radio-si4713: convert to the control framework
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Eduardo Valentin <edubezval@gmail.com>
Tested-by: Eduardo Valentin <edubezval@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/radio/radio-si4713.c | 89 | ||||
-rw-r--r-- | drivers/media/radio/si4713-i2c.c | 908 | ||||
-rw-r--r-- | drivers/media/radio/si4713-i2c.h | 65 |
3 files changed, 239 insertions, 823 deletions
diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c index 633c545438f7..f8c6137573a8 100644 --- a/drivers/media/radio/radio-si4713.c +++ b/drivers/media/radio/radio-si4713.c | |||
@@ -76,61 +76,6 @@ static int radio_si4713_querycap(struct file *file, void *priv, | |||
76 | return 0; | 76 | return 0; |
77 | } | 77 | } |
78 | 78 | ||
79 | /* radio_si4713_queryctrl - enumerate control items */ | ||
80 | static int radio_si4713_queryctrl(struct file *file, void *priv, | ||
81 | struct v4l2_queryctrl *qc) | ||
82 | { | ||
83 | /* Must be sorted from low to high control ID! */ | ||
84 | static const u32 user_ctrls[] = { | ||
85 | V4L2_CID_USER_CLASS, | ||
86 | V4L2_CID_AUDIO_MUTE, | ||
87 | 0 | ||
88 | }; | ||
89 | |||
90 | /* Must be sorted from low to high control ID! */ | ||
91 | static const u32 fmtx_ctrls[] = { | ||
92 | V4L2_CID_FM_TX_CLASS, | ||
93 | V4L2_CID_RDS_TX_DEVIATION, | ||
94 | V4L2_CID_RDS_TX_PI, | ||
95 | V4L2_CID_RDS_TX_PTY, | ||
96 | V4L2_CID_RDS_TX_PS_NAME, | ||
97 | V4L2_CID_RDS_TX_RADIO_TEXT, | ||
98 | V4L2_CID_AUDIO_LIMITER_ENABLED, | ||
99 | V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, | ||
100 | V4L2_CID_AUDIO_LIMITER_DEVIATION, | ||
101 | V4L2_CID_AUDIO_COMPRESSION_ENABLED, | ||
102 | V4L2_CID_AUDIO_COMPRESSION_GAIN, | ||
103 | V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, | ||
104 | V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, | ||
105 | V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, | ||
106 | V4L2_CID_PILOT_TONE_ENABLED, | ||
107 | V4L2_CID_PILOT_TONE_DEVIATION, | ||
108 | V4L2_CID_PILOT_TONE_FREQUENCY, | ||
109 | V4L2_CID_TUNE_PREEMPHASIS, | ||
110 | V4L2_CID_TUNE_POWER_LEVEL, | ||
111 | V4L2_CID_TUNE_ANTENNA_CAPACITOR, | ||
112 | 0 | ||
113 | }; | ||
114 | static const u32 *ctrl_classes[] = { | ||
115 | user_ctrls, | ||
116 | fmtx_ctrls, | ||
117 | NULL | ||
118 | }; | ||
119 | struct radio_si4713_device *rsdev; | ||
120 | |||
121 | rsdev = video_get_drvdata(video_devdata(file)); | ||
122 | |||
123 | qc->id = v4l2_ctrl_next(ctrl_classes, qc->id); | ||
124 | if (qc->id == 0) | ||
125 | return -EINVAL; | ||
126 | |||
127 | if (qc->id == V4L2_CID_USER_CLASS || qc->id == V4L2_CID_FM_TX_CLASS) | ||
128 | return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0); | ||
129 | |||
130 | return v4l2_device_call_until_err(&rsdev->v4l2_dev, 0, core, | ||
131 | queryctrl, qc); | ||
132 | } | ||
133 | |||
134 | /* | 79 | /* |
135 | * v4l2 ioctl call backs. | 80 | * v4l2 ioctl call backs. |
136 | * we are just a wrapper for v4l2_sub_devs. | 81 | * we are just a wrapper for v4l2_sub_devs. |
@@ -140,34 +85,6 @@ static inline struct v4l2_device *get_v4l2_dev(struct file *file) | |||
140 | return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev; | 85 | return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev; |
141 | } | 86 | } |
142 | 87 | ||
143 | static int radio_si4713_g_ext_ctrls(struct file *file, void *p, | ||
144 | struct v4l2_ext_controls *vecs) | ||
145 | { | ||
146 | return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, | ||
147 | g_ext_ctrls, vecs); | ||
148 | } | ||
149 | |||
150 | static int radio_si4713_s_ext_ctrls(struct file *file, void *p, | ||
151 | struct v4l2_ext_controls *vecs) | ||
152 | { | ||
153 | return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, | ||
154 | s_ext_ctrls, vecs); | ||
155 | } | ||
156 | |||
157 | static int radio_si4713_g_ctrl(struct file *file, void *p, | ||
158 | struct v4l2_control *vc) | ||
159 | { | ||
160 | return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, | ||
161 | g_ctrl, vc); | ||
162 | } | ||
163 | |||
164 | static int radio_si4713_s_ctrl(struct file *file, void *p, | ||
165 | struct v4l2_control *vc) | ||
166 | { | ||
167 | return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, | ||
168 | s_ctrl, vc); | ||
169 | } | ||
170 | |||
171 | static int radio_si4713_g_modulator(struct file *file, void *p, | 88 | static int radio_si4713_g_modulator(struct file *file, void *p, |
172 | struct v4l2_modulator *vm) | 89 | struct v4l2_modulator *vm) |
173 | { | 90 | { |
@@ -205,11 +122,6 @@ static long radio_si4713_default(struct file *file, void *p, | |||
205 | 122 | ||
206 | static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = { | 123 | static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = { |
207 | .vidioc_querycap = radio_si4713_querycap, | 124 | .vidioc_querycap = radio_si4713_querycap, |
208 | .vidioc_queryctrl = radio_si4713_queryctrl, | ||
209 | .vidioc_g_ext_ctrls = radio_si4713_g_ext_ctrls, | ||
210 | .vidioc_s_ext_ctrls = radio_si4713_s_ext_ctrls, | ||
211 | .vidioc_g_ctrl = radio_si4713_g_ctrl, | ||
212 | .vidioc_s_ctrl = radio_si4713_s_ctrl, | ||
213 | .vidioc_g_modulator = radio_si4713_g_modulator, | 125 | .vidioc_g_modulator = radio_si4713_g_modulator, |
214 | .vidioc_s_modulator = radio_si4713_s_modulator, | 126 | .vidioc_s_modulator = radio_si4713_s_modulator, |
215 | .vidioc_g_frequency = radio_si4713_g_frequency, | 127 | .vidioc_g_frequency = radio_si4713_g_frequency, |
@@ -274,6 +186,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev) | |||
274 | 186 | ||
275 | rsdev->radio_dev = radio_si4713_vdev_template; | 187 | rsdev->radio_dev = radio_si4713_vdev_template; |
276 | rsdev->radio_dev.v4l2_dev = &rsdev->v4l2_dev; | 188 | rsdev->radio_dev.v4l2_dev = &rsdev->v4l2_dev; |
189 | rsdev->radio_dev.ctrl_handler = sd->ctrl_handler; | ||
277 | /* Serialize all access to the si4713 */ | 190 | /* Serialize all access to the si4713 */ |
278 | rsdev->radio_dev.lock = &rsdev->lock; | 191 | rsdev->radio_dev.lock = &rsdev->lock; |
279 | video_set_drvdata(&rsdev->radio_dev, rsdev); | 192 | video_set_drvdata(&rsdev->radio_dev, rsdev); |
diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c index 56c9241ee7fb..fe160882ee10 100644 --- a/drivers/media/radio/si4713-i2c.c +++ b/drivers/media/radio/si4713-i2c.c | |||
@@ -52,8 +52,6 @@ static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = { | |||
52 | 52 | ||
53 | #define DEFAULT_RDS_PI 0x00 | 53 | #define DEFAULT_RDS_PI 0x00 |
54 | #define DEFAULT_RDS_PTY 0x00 | 54 | #define DEFAULT_RDS_PTY 0x00 |
55 | #define DEFAULT_RDS_PS_NAME "" | ||
56 | #define DEFAULT_RDS_RADIO_TEXT DEFAULT_RDS_PS_NAME | ||
57 | #define DEFAULT_RDS_DEVIATION 0x00C8 | 55 | #define DEFAULT_RDS_DEVIATION 0x00C8 |
58 | #define DEFAULT_RDS_PS_REPEAT_COUNT 0x0003 | 56 | #define DEFAULT_RDS_PS_REPEAT_COUNT 0x0003 |
59 | #define DEFAULT_LIMITER_RTIME 0x1392 | 57 | #define DEFAULT_LIMITER_RTIME 0x1392 |
@@ -107,7 +105,6 @@ static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = { | |||
107 | (status & SI4713_ERR)) | 105 | (status & SI4713_ERR)) |
108 | /* mute definition */ | 106 | /* mute definition */ |
109 | #define set_mute(p) ((p & 1) | ((p & 1) << 1)); | 107 | #define set_mute(p) ((p & 1) | ((p & 1) << 1)); |
110 | #define get_mute(p) (p & 0x01) | ||
111 | 108 | ||
112 | #ifdef DEBUG | 109 | #ifdef DEBUG |
113 | #define DBG_BUFFER(device, message, buffer, size) \ | 110 | #define DBG_BUFFER(device, message, buffer, size) \ |
@@ -189,21 +186,6 @@ static int usecs_to_dev(unsigned long usecs, unsigned long const array[], | |||
189 | return rval; | 186 | return rval; |
190 | } | 187 | } |
191 | 188 | ||
192 | static unsigned long dev_to_usecs(int value, unsigned long const array[], | ||
193 | int size) | ||
194 | { | ||
195 | int i; | ||
196 | int rval = -EINVAL; | ||
197 | |||
198 | for (i = 0; i < size / 2; i++) | ||
199 | if (array[i * 2] == value) { | ||
200 | rval = array[(i * 2) + 1]; | ||
201 | break; | ||
202 | } | ||
203 | |||
204 | return rval; | ||
205 | } | ||
206 | |||
207 | /* si4713_handler: IRQ handler, just complete work */ | 189 | /* si4713_handler: IRQ handler, just complete work */ |
208 | static irqreturn_t si4713_handler(int irq, void *dev) | 190 | static irqreturn_t si4713_handler(int irq, void *dev) |
209 | { | 191 | { |
@@ -787,9 +769,6 @@ static int si4713_set_mute(struct si4713_device *sdev, u16 mute) | |||
787 | rval = si4713_write_property(sdev, | 769 | rval = si4713_write_property(sdev, |
788 | SI4713_TX_LINE_INPUT_MUTE, mute); | 770 | SI4713_TX_LINE_INPUT_MUTE, mute); |
789 | 771 | ||
790 | if (rval >= 0) | ||
791 | sdev->mute = get_mute(mute); | ||
792 | |||
793 | return rval; | 772 | return rval; |
794 | } | 773 | } |
795 | 774 | ||
@@ -830,7 +809,6 @@ static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name) | |||
830 | return rval; | 809 | return rval; |
831 | } | 810 | } |
832 | 811 | ||
833 | strncpy(sdev->rds_info.ps_name, ps_name, MAX_RDS_PS_NAME); | ||
834 | return rval; | 812 | return rval; |
835 | } | 813 | } |
836 | 814 | ||
@@ -842,24 +820,23 @@ static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt) | |||
842 | s8 left; | 820 | s8 left; |
843 | 821 | ||
844 | if (!sdev->power_state) | 822 | if (!sdev->power_state) |
845 | goto copy; | 823 | return rval; |
846 | 824 | ||
847 | rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left); | 825 | rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left); |
848 | if (rval < 0) | 826 | if (rval < 0) |
849 | return rval; | 827 | return rval; |
850 | 828 | ||
851 | if (!strlen(rt)) | 829 | if (!strlen(rt)) |
852 | goto copy; | 830 | return rval; |
853 | 831 | ||
854 | do { | 832 | do { |
855 | /* RDS spec says that if the last block isn't used, | 833 | /* RDS spec says that if the last block isn't used, |
856 | * then apply a carriage return | 834 | * then apply a carriage return |
857 | */ | 835 | */ |
858 | if (t_index < (RDS_RADIOTEXT_INDEX_MAX * | 836 | if (t_index < (RDS_RADIOTEXT_INDEX_MAX * RDS_RADIOTEXT_BLK_SIZE)) { |
859 | RDS_RADIOTEXT_BLK_SIZE)) { | ||
860 | for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) { | 837 | for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) { |
861 | if (!rt[t_index + i] || rt[t_index + i] == | 838 | if (!rt[t_index + i] || |
862 | RDS_CARRIAGE_RETURN) { | 839 | rt[t_index + i] == RDS_CARRIAGE_RETURN) { |
863 | rt[t_index + i] = RDS_CARRIAGE_RETURN; | 840 | rt[t_index + i] = RDS_CARRIAGE_RETURN; |
864 | cr_inserted = 1; | 841 | cr_inserted = 1; |
865 | break; | 842 | break; |
@@ -881,13 +858,38 @@ static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt) | |||
881 | break; | 858 | break; |
882 | } while (left > 0); | 859 | } while (left > 0); |
883 | 860 | ||
884 | copy: | 861 | return rval; |
885 | strncpy(sdev->rds_info.radio_text, rt, MAX_RDS_RADIO_TEXT); | 862 | } |
863 | |||
864 | /* | ||
865 | * si4713_update_tune_status - update properties from tx_tune_status | ||
866 | * command. Must be called with sdev->mutex held. | ||
867 | * @sdev: si4713_device structure for the device we are communicating | ||
868 | */ | ||
869 | static int si4713_update_tune_status(struct si4713_device *sdev) | ||
870 | { | ||
871 | int rval; | ||
872 | u16 f = 0; | ||
873 | u8 p = 0, a = 0, n = 0; | ||
874 | |||
875 | rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n); | ||
876 | |||
877 | if (rval < 0) | ||
878 | goto exit; | ||
879 | |||
880 | /* TODO: check that power_level and antenna_capacitor really are not | ||
881 | changed by the hardware. If they are, then these controls should become | ||
882 | volatiles. | ||
883 | sdev->power_level = p; | ||
884 | sdev->antenna_capacitor = a;*/ | ||
885 | sdev->tune_rnl = n; | ||
886 | |||
887 | exit: | ||
886 | return rval; | 888 | return rval; |
887 | } | 889 | } |
888 | 890 | ||
889 | static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id, | 891 | static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id, |
890 | u32 **shadow, s32 *bit, s32 *mask, u16 *property, int *mul, | 892 | s32 *bit, s32 *mask, u16 *property, int *mul, |
891 | unsigned long **table, int *size) | 893 | unsigned long **table, int *size) |
892 | { | 894 | { |
893 | s32 rval = 0; | 895 | s32 rval = 0; |
@@ -897,277 +899,76 @@ static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id, | |||
897 | case V4L2_CID_RDS_TX_PI: | 899 | case V4L2_CID_RDS_TX_PI: |
898 | *property = SI4713_TX_RDS_PI; | 900 | *property = SI4713_TX_RDS_PI; |
899 | *mul = 1; | 901 | *mul = 1; |
900 | *shadow = &sdev->rds_info.pi; | ||
901 | break; | 902 | break; |
902 | case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: | 903 | case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: |
903 | *property = SI4713_TX_ACOMP_THRESHOLD; | 904 | *property = SI4713_TX_ACOMP_THRESHOLD; |
904 | *mul = 1; | 905 | *mul = 1; |
905 | *shadow = &sdev->acomp_info.threshold; | ||
906 | break; | 906 | break; |
907 | case V4L2_CID_AUDIO_COMPRESSION_GAIN: | 907 | case V4L2_CID_AUDIO_COMPRESSION_GAIN: |
908 | *property = SI4713_TX_ACOMP_GAIN; | 908 | *property = SI4713_TX_ACOMP_GAIN; |
909 | *mul = 1; | 909 | *mul = 1; |
910 | *shadow = &sdev->acomp_info.gain; | ||
911 | break; | 910 | break; |
912 | case V4L2_CID_PILOT_TONE_FREQUENCY: | 911 | case V4L2_CID_PILOT_TONE_FREQUENCY: |
913 | *property = SI4713_TX_PILOT_FREQUENCY; | 912 | *property = SI4713_TX_PILOT_FREQUENCY; |
914 | *mul = 1; | 913 | *mul = 1; |
915 | *shadow = &sdev->pilot_info.frequency; | ||
916 | break; | 914 | break; |
917 | case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: | 915 | case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: |
918 | *property = SI4713_TX_ACOMP_ATTACK_TIME; | 916 | *property = SI4713_TX_ACOMP_ATTACK_TIME; |
919 | *mul = ATTACK_TIME_UNIT; | 917 | *mul = ATTACK_TIME_UNIT; |
920 | *shadow = &sdev->acomp_info.attack_time; | ||
921 | break; | 918 | break; |
922 | case V4L2_CID_PILOT_TONE_DEVIATION: | 919 | case V4L2_CID_PILOT_TONE_DEVIATION: |
923 | *property = SI4713_TX_PILOT_DEVIATION; | 920 | *property = SI4713_TX_PILOT_DEVIATION; |
924 | *mul = 10; | 921 | *mul = 10; |
925 | *shadow = &sdev->pilot_info.deviation; | ||
926 | break; | 922 | break; |
927 | case V4L2_CID_AUDIO_LIMITER_DEVIATION: | 923 | case V4L2_CID_AUDIO_LIMITER_DEVIATION: |
928 | *property = SI4713_TX_AUDIO_DEVIATION; | 924 | *property = SI4713_TX_AUDIO_DEVIATION; |
929 | *mul = 10; | 925 | *mul = 10; |
930 | *shadow = &sdev->limiter_info.deviation; | ||
931 | break; | 926 | break; |
932 | case V4L2_CID_RDS_TX_DEVIATION: | 927 | case V4L2_CID_RDS_TX_DEVIATION: |
933 | *property = SI4713_TX_RDS_DEVIATION; | 928 | *property = SI4713_TX_RDS_DEVIATION; |
934 | *mul = 1; | 929 | *mul = 1; |
935 | *shadow = &sdev->rds_info.deviation; | ||
936 | break; | 930 | break; |
937 | 931 | ||
938 | case V4L2_CID_RDS_TX_PTY: | 932 | case V4L2_CID_RDS_TX_PTY: |
939 | *property = SI4713_TX_RDS_PS_MISC; | 933 | *property = SI4713_TX_RDS_PS_MISC; |
940 | *bit = 5; | 934 | *bit = 5; |
941 | *mask = 0x1F << 5; | 935 | *mask = 0x1F << 5; |
942 | *shadow = &sdev->rds_info.pty; | ||
943 | break; | 936 | break; |
944 | case V4L2_CID_AUDIO_LIMITER_ENABLED: | 937 | case V4L2_CID_AUDIO_LIMITER_ENABLED: |
945 | *property = SI4713_TX_ACOMP_ENABLE; | 938 | *property = SI4713_TX_ACOMP_ENABLE; |
946 | *bit = 1; | 939 | *bit = 1; |
947 | *mask = 1 << 1; | 940 | *mask = 1 << 1; |
948 | *shadow = &sdev->limiter_info.enabled; | ||
949 | break; | 941 | break; |
950 | case V4L2_CID_AUDIO_COMPRESSION_ENABLED: | 942 | case V4L2_CID_AUDIO_COMPRESSION_ENABLED: |
951 | *property = SI4713_TX_ACOMP_ENABLE; | 943 | *property = SI4713_TX_ACOMP_ENABLE; |
952 | *bit = 0; | 944 | *bit = 0; |
953 | *mask = 1 << 0; | 945 | *mask = 1 << 0; |
954 | *shadow = &sdev->acomp_info.enabled; | ||
955 | break; | 946 | break; |
956 | case V4L2_CID_PILOT_TONE_ENABLED: | 947 | case V4L2_CID_PILOT_TONE_ENABLED: |
957 | *property = SI4713_TX_COMPONENT_ENABLE; | 948 | *property = SI4713_TX_COMPONENT_ENABLE; |
958 | *bit = 0; | 949 | *bit = 0; |
959 | *mask = 1 << 0; | 950 | *mask = 1 << 0; |
960 | *shadow = &sdev->pilot_info.enabled; | ||
961 | break; | 951 | break; |
962 | 952 | ||
963 | case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: | 953 | case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: |
964 | *property = SI4713_TX_LIMITER_RELEASE_TIME; | 954 | *property = SI4713_TX_LIMITER_RELEASE_TIME; |
965 | *table = limiter_times; | 955 | *table = limiter_times; |
966 | *size = ARRAY_SIZE(limiter_times); | 956 | *size = ARRAY_SIZE(limiter_times); |
967 | *shadow = &sdev->limiter_info.release_time; | ||
968 | break; | 957 | break; |
969 | case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: | 958 | case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: |
970 | *property = SI4713_TX_ACOMP_RELEASE_TIME; | 959 | *property = SI4713_TX_ACOMP_RELEASE_TIME; |
971 | *table = acomp_rtimes; | 960 | *table = acomp_rtimes; |
972 | *size = ARRAY_SIZE(acomp_rtimes); | 961 | *size = ARRAY_SIZE(acomp_rtimes); |
973 | *shadow = &sdev->acomp_info.release_time; | ||
974 | break; | 962 | break; |
975 | case V4L2_CID_TUNE_PREEMPHASIS: | 963 | case V4L2_CID_TUNE_PREEMPHASIS: |
976 | *property = SI4713_TX_PREEMPHASIS; | 964 | *property = SI4713_TX_PREEMPHASIS; |
977 | *table = preemphasis_values; | 965 | *table = preemphasis_values; |
978 | *size = ARRAY_SIZE(preemphasis_values); | 966 | *size = ARRAY_SIZE(preemphasis_values); |
979 | *shadow = &sdev->preemphasis; | ||
980 | break; | 967 | break; |
981 | 968 | ||
982 | default: | 969 | default: |
983 | rval = -EINVAL; | 970 | rval = -EINVAL; |
984 | } | ||
985 | |||
986 | return rval; | ||
987 | } | ||
988 | |||
989 | static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc); | ||
990 | |||
991 | /* write string property */ | ||
992 | static int si4713_write_econtrol_string(struct si4713_device *sdev, | ||
993 | struct v4l2_ext_control *control) | ||
994 | { | ||
995 | struct v4l2_queryctrl vqc; | ||
996 | int len; | ||
997 | s32 rval = 0; | ||
998 | |||
999 | vqc.id = control->id; | ||
1000 | rval = si4713_queryctrl(&sdev->sd, &vqc); | ||
1001 | if (rval < 0) | ||
1002 | goto exit; | ||
1003 | |||
1004 | switch (control->id) { | ||
1005 | case V4L2_CID_RDS_TX_PS_NAME: { | ||
1006 | char ps_name[MAX_RDS_PS_NAME + 1]; | ||
1007 | |||
1008 | len = control->size - 1; | ||
1009 | if (len < 0 || len > MAX_RDS_PS_NAME) { | ||
1010 | rval = -ERANGE; | ||
1011 | goto exit; | ||
1012 | } | ||
1013 | rval = copy_from_user(ps_name, control->string, len); | ||
1014 | if (rval) { | ||
1015 | rval = -EFAULT; | ||
1016 | goto exit; | ||
1017 | } | ||
1018 | ps_name[len] = '\0'; | ||
1019 | |||
1020 | if (strlen(ps_name) % vqc.step) { | ||
1021 | rval = -ERANGE; | ||
1022 | goto exit; | ||
1023 | } | ||
1024 | |||
1025 | rval = si4713_set_rds_ps_name(sdev, ps_name); | ||
1026 | } | ||
1027 | break; | ||
1028 | |||
1029 | case V4L2_CID_RDS_TX_RADIO_TEXT: { | ||
1030 | char radio_text[MAX_RDS_RADIO_TEXT + 1]; | ||
1031 | |||
1032 | len = control->size - 1; | ||
1033 | if (len < 0 || len > MAX_RDS_RADIO_TEXT) { | ||
1034 | rval = -ERANGE; | ||
1035 | goto exit; | ||
1036 | } | ||
1037 | rval = copy_from_user(radio_text, control->string, len); | ||
1038 | if (rval) { | ||
1039 | rval = -EFAULT; | ||
1040 | goto exit; | ||
1041 | } | ||
1042 | radio_text[len] = '\0'; | ||
1043 | |||
1044 | if (strlen(radio_text) % vqc.step) { | ||
1045 | rval = -ERANGE; | ||
1046 | goto exit; | ||
1047 | } | ||
1048 | |||
1049 | rval = si4713_set_rds_radio_text(sdev, radio_text); | ||
1050 | } | ||
1051 | break; | ||
1052 | |||
1053 | default: | ||
1054 | rval = -EINVAL; | ||
1055 | break; | ||
1056 | } | ||
1057 | |||
1058 | exit: | ||
1059 | return rval; | ||
1060 | } | ||
1061 | |||
1062 | static int validate_range(struct v4l2_subdev *sd, | ||
1063 | struct v4l2_ext_control *control) | ||
1064 | { | ||
1065 | struct v4l2_queryctrl vqc; | ||
1066 | int rval; | ||
1067 | |||
1068 | vqc.id = control->id; | ||
1069 | rval = si4713_queryctrl(sd, &vqc); | ||
1070 | if (rval < 0) | ||
1071 | goto exit; | ||
1072 | |||
1073 | if (control->value < vqc.minimum || control->value > vqc.maximum) | ||
1074 | rval = -ERANGE; | ||
1075 | |||
1076 | exit: | ||
1077 | return rval; | ||
1078 | } | ||
1079 | |||
1080 | /* properties which use tx_tune_power*/ | ||
1081 | static int si4713_write_econtrol_tune(struct si4713_device *sdev, | ||
1082 | struct v4l2_ext_control *control) | ||
1083 | { | ||
1084 | s32 rval = 0; | ||
1085 | u8 power, antcap; | ||
1086 | |||
1087 | rval = validate_range(&sdev->sd, control); | ||
1088 | if (rval < 0) | ||
1089 | return rval; | ||
1090 | |||
1091 | switch (control->id) { | ||
1092 | case V4L2_CID_TUNE_POWER_LEVEL: | ||
1093 | power = control->value; | ||
1094 | antcap = sdev->antenna_capacitor; | ||
1095 | break; | ||
1096 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | ||
1097 | power = sdev->power_level; | ||
1098 | antcap = control->value; | ||
1099 | break; | 971 | break; |
1100 | default: | ||
1101 | return -EINVAL; | ||
1102 | } | ||
1103 | |||
1104 | if (sdev->power_state) | ||
1105 | rval = si4713_tx_tune_power(sdev, power, antcap); | ||
1106 | |||
1107 | if (rval == 0) { | ||
1108 | sdev->power_level = power; | ||
1109 | sdev->antenna_capacitor = antcap; | ||
1110 | } | ||
1111 | |||
1112 | return rval; | ||
1113 | } | ||
1114 | |||
1115 | static int si4713_write_econtrol_integers(struct si4713_device *sdev, | ||
1116 | struct v4l2_ext_control *control) | ||
1117 | { | ||
1118 | s32 rval; | ||
1119 | u32 *shadow = NULL, val = 0; | ||
1120 | s32 bit = 0, mask = 0; | ||
1121 | u16 property = 0; | ||
1122 | int mul = 0; | ||
1123 | unsigned long *table = NULL; | ||
1124 | int size = 0; | ||
1125 | |||
1126 | rval = validate_range(&sdev->sd, control); | ||
1127 | if (rval < 0) | ||
1128 | return rval; | ||
1129 | |||
1130 | rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, | ||
1131 | &mask, &property, &mul, &table, &size); | ||
1132 | if (rval < 0) | ||
1133 | return rval; | ||
1134 | |||
1135 | val = control->value; | ||
1136 | if (mul) { | ||
1137 | val = control->value / mul; | ||
1138 | } else if (table) { | ||
1139 | rval = usecs_to_dev(control->value, table, size); | ||
1140 | if (rval < 0) | ||
1141 | return rval; | ||
1142 | val = rval; | ||
1143 | rval = 0; | ||
1144 | } | ||
1145 | |||
1146 | if (sdev->power_state) { | ||
1147 | if (mask) { | ||
1148 | rval = si4713_read_property(sdev, property, &val); | ||
1149 | if (rval < 0) | ||
1150 | return rval; | ||
1151 | val = set_bits(val, control->value, bit, mask); | ||
1152 | } | ||
1153 | |||
1154 | rval = si4713_write_property(sdev, property, val); | ||
1155 | if (rval < 0) | ||
1156 | return rval; | ||
1157 | if (mask) | ||
1158 | val = control->value; | ||
1159 | } | ||
1160 | |||
1161 | if (mul) { | ||
1162 | *shadow = val * mul; | ||
1163 | } else if (table) { | ||
1164 | rval = dev_to_usecs(val, table, size); | ||
1165 | if (rval < 0) | ||
1166 | return rval; | ||
1167 | *shadow = rval; | ||
1168 | rval = 0; | ||
1169 | } else { | ||
1170 | *shadow = val; | ||
1171 | } | 972 | } |
1172 | 973 | ||
1173 | return rval; | 974 | return rval; |
@@ -1181,110 +982,25 @@ static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulato | |||
1181 | */ | 982 | */ |
1182 | static int si4713_setup(struct si4713_device *sdev) | 983 | static int si4713_setup(struct si4713_device *sdev) |
1183 | { | 984 | { |
1184 | struct v4l2_ext_control ctrl; | ||
1185 | struct v4l2_frequency f; | 985 | struct v4l2_frequency f; |
1186 | struct v4l2_modulator vm; | 986 | struct v4l2_modulator vm; |
1187 | struct si4713_device *tmp; | 987 | int rval; |
1188 | int rval = 0; | ||
1189 | |||
1190 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | ||
1191 | if (!tmp) | ||
1192 | return -ENOMEM; | ||
1193 | |||
1194 | /* Get a local copy to avoid race */ | ||
1195 | memcpy(tmp, sdev, sizeof(*sdev)); | ||
1196 | |||
1197 | ctrl.id = V4L2_CID_RDS_TX_PI; | ||
1198 | ctrl.value = tmp->rds_info.pi; | ||
1199 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1200 | |||
1201 | ctrl.id = V4L2_CID_AUDIO_COMPRESSION_THRESHOLD; | ||
1202 | ctrl.value = tmp->acomp_info.threshold; | ||
1203 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1204 | |||
1205 | ctrl.id = V4L2_CID_AUDIO_COMPRESSION_GAIN; | ||
1206 | ctrl.value = tmp->acomp_info.gain; | ||
1207 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1208 | |||
1209 | ctrl.id = V4L2_CID_PILOT_TONE_FREQUENCY; | ||
1210 | ctrl.value = tmp->pilot_info.frequency; | ||
1211 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1212 | |||
1213 | ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME; | ||
1214 | ctrl.value = tmp->acomp_info.attack_time; | ||
1215 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1216 | |||
1217 | ctrl.id = V4L2_CID_PILOT_TONE_DEVIATION; | ||
1218 | ctrl.value = tmp->pilot_info.deviation; | ||
1219 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1220 | |||
1221 | ctrl.id = V4L2_CID_AUDIO_LIMITER_DEVIATION; | ||
1222 | ctrl.value = tmp->limiter_info.deviation; | ||
1223 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1224 | |||
1225 | ctrl.id = V4L2_CID_RDS_TX_DEVIATION; | ||
1226 | ctrl.value = tmp->rds_info.deviation; | ||
1227 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1228 | |||
1229 | ctrl.id = V4L2_CID_RDS_TX_PTY; | ||
1230 | ctrl.value = tmp->rds_info.pty; | ||
1231 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1232 | |||
1233 | ctrl.id = V4L2_CID_AUDIO_LIMITER_ENABLED; | ||
1234 | ctrl.value = tmp->limiter_info.enabled; | ||
1235 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1236 | |||
1237 | ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ENABLED; | ||
1238 | ctrl.value = tmp->acomp_info.enabled; | ||
1239 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1240 | |||
1241 | ctrl.id = V4L2_CID_PILOT_TONE_ENABLED; | ||
1242 | ctrl.value = tmp->pilot_info.enabled; | ||
1243 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1244 | |||
1245 | ctrl.id = V4L2_CID_AUDIO_LIMITER_RELEASE_TIME; | ||
1246 | ctrl.value = tmp->limiter_info.release_time; | ||
1247 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1248 | |||
1249 | ctrl.id = V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME; | ||
1250 | ctrl.value = tmp->acomp_info.release_time; | ||
1251 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1252 | |||
1253 | ctrl.id = V4L2_CID_TUNE_PREEMPHASIS; | ||
1254 | ctrl.value = tmp->preemphasis; | ||
1255 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1256 | |||
1257 | ctrl.id = V4L2_CID_RDS_TX_PS_NAME; | ||
1258 | rval |= si4713_set_rds_ps_name(sdev, tmp->rds_info.ps_name); | ||
1259 | |||
1260 | ctrl.id = V4L2_CID_RDS_TX_RADIO_TEXT; | ||
1261 | rval |= si4713_set_rds_radio_text(sdev, tmp->rds_info.radio_text); | ||
1262 | 988 | ||
1263 | /* Device procedure needs to set frequency first */ | 989 | /* Device procedure needs to set frequency first */ |
1264 | f.tuner = 0; | 990 | f.tuner = 0; |
1265 | f.frequency = tmp->frequency ? tmp->frequency : DEFAULT_FREQUENCY; | 991 | f.frequency = sdev->frequency ? sdev->frequency : DEFAULT_FREQUENCY; |
1266 | f.frequency = si4713_to_v4l2(f.frequency); | 992 | f.frequency = si4713_to_v4l2(f.frequency); |
1267 | rval |= si4713_s_frequency(&sdev->sd, &f); | 993 | rval = si4713_s_frequency(&sdev->sd, &f); |
1268 | |||
1269 | ctrl.id = V4L2_CID_TUNE_POWER_LEVEL; | ||
1270 | ctrl.value = tmp->power_level; | ||
1271 | rval |= si4713_write_econtrol_tune(sdev, &ctrl); | ||
1272 | |||
1273 | ctrl.id = V4L2_CID_TUNE_ANTENNA_CAPACITOR; | ||
1274 | ctrl.value = tmp->antenna_capacitor; | ||
1275 | rval |= si4713_write_econtrol_tune(sdev, &ctrl); | ||
1276 | 994 | ||
1277 | vm.index = 0; | 995 | vm.index = 0; |
1278 | if (tmp->stereo) | 996 | if (sdev->stereo) |
1279 | vm.txsubchans = V4L2_TUNER_SUB_STEREO; | 997 | vm.txsubchans = V4L2_TUNER_SUB_STEREO; |
1280 | else | 998 | else |
1281 | vm.txsubchans = V4L2_TUNER_SUB_MONO; | 999 | vm.txsubchans = V4L2_TUNER_SUB_MONO; |
1282 | if (tmp->rds_info.enabled) | 1000 | if (sdev->rds_enabled) |
1283 | vm.txsubchans |= V4L2_TUNER_SUB_RDS; | 1001 | vm.txsubchans |= V4L2_TUNER_SUB_RDS; |
1284 | si4713_s_modulator(&sdev->sd, &vm); | 1002 | si4713_s_modulator(&sdev->sd, &vm); |
1285 | 1003 | ||
1286 | kfree(tmp); | ||
1287 | |||
1288 | return rval; | 1004 | return rval; |
1289 | } | 1005 | } |
1290 | 1006 | ||
@@ -1308,406 +1024,116 @@ static int si4713_initialize(struct si4713_device *sdev) | |||
1308 | if (rval < 0) | 1024 | if (rval < 0) |
1309 | return rval; | 1025 | return rval; |
1310 | 1026 | ||
1311 | sdev->rds_info.pi = DEFAULT_RDS_PI; | ||
1312 | sdev->rds_info.pty = DEFAULT_RDS_PTY; | ||
1313 | sdev->rds_info.deviation = DEFAULT_RDS_DEVIATION; | ||
1314 | strlcpy(sdev->rds_info.ps_name, DEFAULT_RDS_PS_NAME, MAX_RDS_PS_NAME); | ||
1315 | strlcpy(sdev->rds_info.radio_text, DEFAULT_RDS_RADIO_TEXT, | ||
1316 | MAX_RDS_RADIO_TEXT); | ||
1317 | sdev->rds_info.enabled = 1; | ||
1318 | |||
1319 | sdev->limiter_info.release_time = DEFAULT_LIMITER_RTIME; | ||
1320 | sdev->limiter_info.deviation = DEFAULT_LIMITER_DEV; | ||
1321 | sdev->limiter_info.enabled = 1; | ||
1322 | |||
1323 | sdev->pilot_info.deviation = DEFAULT_PILOT_DEVIATION; | ||
1324 | sdev->pilot_info.frequency = DEFAULT_PILOT_FREQUENCY; | ||
1325 | sdev->pilot_info.enabled = 1; | ||
1326 | |||
1327 | sdev->acomp_info.release_time = DEFAULT_ACOMP_RTIME; | ||
1328 | sdev->acomp_info.attack_time = DEFAULT_ACOMP_ATIME; | ||
1329 | sdev->acomp_info.threshold = DEFAULT_ACOMP_THRESHOLD; | ||
1330 | sdev->acomp_info.gain = DEFAULT_ACOMP_GAIN; | ||
1331 | sdev->acomp_info.enabled = 1; | ||
1332 | 1027 | ||
1333 | sdev->frequency = DEFAULT_FREQUENCY; | 1028 | sdev->frequency = DEFAULT_FREQUENCY; |
1334 | sdev->preemphasis = DEFAULT_PREEMPHASIS; | ||
1335 | sdev->mute = DEFAULT_MUTE; | ||
1336 | sdev->power_level = DEFAULT_POWER_LEVEL; | ||
1337 | sdev->antenna_capacitor = 0; | ||
1338 | sdev->stereo = 1; | 1029 | sdev->stereo = 1; |
1339 | sdev->tune_rnl = DEFAULT_TUNE_RNL; | 1030 | sdev->tune_rnl = DEFAULT_TUNE_RNL; |
1340 | 1031 | return 0; | |
1341 | return rval; | ||
1342 | } | ||
1343 | |||
1344 | /* read string property */ | ||
1345 | static int si4713_read_econtrol_string(struct si4713_device *sdev, | ||
1346 | struct v4l2_ext_control *control) | ||
1347 | { | ||
1348 | s32 rval = 0; | ||
1349 | |||
1350 | switch (control->id) { | ||
1351 | case V4L2_CID_RDS_TX_PS_NAME: | ||
1352 | if (strlen(sdev->rds_info.ps_name) + 1 > control->size) { | ||
1353 | control->size = MAX_RDS_PS_NAME + 1; | ||
1354 | rval = -ENOSPC; | ||
1355 | goto exit; | ||
1356 | } | ||
1357 | rval = copy_to_user(control->string, sdev->rds_info.ps_name, | ||
1358 | strlen(sdev->rds_info.ps_name) + 1); | ||
1359 | if (rval) | ||
1360 | rval = -EFAULT; | ||
1361 | break; | ||
1362 | |||
1363 | case V4L2_CID_RDS_TX_RADIO_TEXT: | ||
1364 | if (strlen(sdev->rds_info.radio_text) + 1 > control->size) { | ||
1365 | control->size = MAX_RDS_RADIO_TEXT + 1; | ||
1366 | rval = -ENOSPC; | ||
1367 | goto exit; | ||
1368 | } | ||
1369 | rval = copy_to_user(control->string, sdev->rds_info.radio_text, | ||
1370 | strlen(sdev->rds_info.radio_text) + 1); | ||
1371 | if (rval) | ||
1372 | rval = -EFAULT; | ||
1373 | break; | ||
1374 | |||
1375 | default: | ||
1376 | rval = -EINVAL; | ||
1377 | break; | ||
1378 | } | ||
1379 | |||
1380 | exit: | ||
1381 | return rval; | ||
1382 | } | ||
1383 | |||
1384 | /* | ||
1385 | * si4713_update_tune_status - update properties from tx_tune_status | ||
1386 | * command. | ||
1387 | * @sdev: si4713_device structure for the device we are communicating | ||
1388 | */ | ||
1389 | static int si4713_update_tune_status(struct si4713_device *sdev) | ||
1390 | { | ||
1391 | int rval; | ||
1392 | u16 f = 0; | ||
1393 | u8 p = 0, a = 0, n = 0; | ||
1394 | |||
1395 | rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n); | ||
1396 | |||
1397 | if (rval < 0) | ||
1398 | goto exit; | ||
1399 | |||
1400 | sdev->power_level = p; | ||
1401 | sdev->antenna_capacitor = a; | ||
1402 | sdev->tune_rnl = n; | ||
1403 | |||
1404 | exit: | ||
1405 | return rval; | ||
1406 | } | ||
1407 | |||
1408 | /* properties which use tx_tune_status */ | ||
1409 | static int si4713_read_econtrol_tune(struct si4713_device *sdev, | ||
1410 | struct v4l2_ext_control *control) | ||
1411 | { | ||
1412 | s32 rval = 0; | ||
1413 | |||
1414 | if (sdev->power_state) { | ||
1415 | rval = si4713_update_tune_status(sdev); | ||
1416 | if (rval < 0) | ||
1417 | return rval; | ||
1418 | } | ||
1419 | |||
1420 | switch (control->id) { | ||
1421 | case V4L2_CID_TUNE_POWER_LEVEL: | ||
1422 | control->value = sdev->power_level; | ||
1423 | break; | ||
1424 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | ||
1425 | control->value = sdev->antenna_capacitor; | ||
1426 | break; | ||
1427 | default: | ||
1428 | return -EINVAL; | ||
1429 | } | ||
1430 | |||
1431 | return rval; | ||
1432 | } | 1032 | } |
1433 | 1033 | ||
1434 | static int si4713_read_econtrol_integers(struct si4713_device *sdev, | 1034 | /* si4713_s_ctrl - set the value of a control */ |
1435 | struct v4l2_ext_control *control) | 1035 | static int si4713_s_ctrl(struct v4l2_ctrl *ctrl) |
1436 | { | 1036 | { |
1437 | s32 rval; | 1037 | struct si4713_device *sdev = |
1438 | u32 *shadow = NULL, val = 0; | 1038 | container_of(ctrl->handler, struct si4713_device, ctrl_handler); |
1039 | u32 val = 0; | ||
1439 | s32 bit = 0, mask = 0; | 1040 | s32 bit = 0, mask = 0; |
1440 | u16 property = 0; | 1041 | u16 property = 0; |
1441 | int mul = 0; | 1042 | int mul = 0; |
1442 | unsigned long *table = NULL; | 1043 | unsigned long *table = NULL; |
1443 | int size = 0; | 1044 | int size = 0; |
1045 | bool force = false; | ||
1046 | int c; | ||
1047 | int ret = 0; | ||
1444 | 1048 | ||
1445 | rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, | 1049 | if (ctrl->id != V4L2_CID_AUDIO_MUTE) |
1446 | &mask, &property, &mul, &table, &size); | ||
1447 | if (rval < 0) | ||
1448 | return rval; | ||
1449 | |||
1450 | if (sdev->power_state) { | ||
1451 | rval = si4713_read_property(sdev, property, &val); | ||
1452 | if (rval < 0) | ||
1453 | return rval; | ||
1454 | |||
1455 | /* Keep negative values for threshold */ | ||
1456 | if (control->id == V4L2_CID_AUDIO_COMPRESSION_THRESHOLD) | ||
1457 | *shadow = (s16)val; | ||
1458 | else if (mask) | ||
1459 | *shadow = get_status_bit(val, bit, mask); | ||
1460 | else if (mul) | ||
1461 | *shadow = val * mul; | ||
1462 | else | ||
1463 | *shadow = dev_to_usecs(val, table, size); | ||
1464 | } | ||
1465 | |||
1466 | control->value = *shadow; | ||
1467 | |||
1468 | return rval; | ||
1469 | } | ||
1470 | |||
1471 | /* | ||
1472 | * Video4Linux Subdev Interface | ||
1473 | */ | ||
1474 | /* si4713_s_ext_ctrls - set extended controls value */ | ||
1475 | static int si4713_s_ext_ctrls(struct v4l2_subdev *sd, | ||
1476 | struct v4l2_ext_controls *ctrls) | ||
1477 | { | ||
1478 | struct si4713_device *sdev = to_si4713_device(sd); | ||
1479 | int i; | ||
1480 | |||
1481 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) | ||
1482 | return -EINVAL; | 1050 | return -EINVAL; |
1483 | 1051 | if (ctrl->is_new) { | |
1484 | for (i = 0; i < ctrls->count; i++) { | 1052 | if (ctrl->val) { |
1485 | int err; | 1053 | ret = si4713_set_mute(sdev, ctrl->val); |
1486 | 1054 | if (!ret) | |
1487 | switch ((ctrls->controls + i)->id) { | 1055 | ret = si4713_set_power_state(sdev, POWER_DOWN); |
1488 | case V4L2_CID_RDS_TX_PS_NAME: | 1056 | return ret; |
1489 | case V4L2_CID_RDS_TX_RADIO_TEXT: | ||
1490 | err = si4713_write_econtrol_string(sdev, | ||
1491 | ctrls->controls + i); | ||
1492 | break; | ||
1493 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | ||
1494 | case V4L2_CID_TUNE_POWER_LEVEL: | ||
1495 | err = si4713_write_econtrol_tune(sdev, | ||
1496 | ctrls->controls + i); | ||
1497 | break; | ||
1498 | default: | ||
1499 | err = si4713_write_econtrol_integers(sdev, | ||
1500 | ctrls->controls + i); | ||
1501 | } | ||
1502 | |||
1503 | if (err < 0) { | ||
1504 | ctrls->error_idx = i; | ||
1505 | return err; | ||
1506 | } | 1057 | } |
1058 | ret = si4713_set_power_state(sdev, POWER_UP); | ||
1059 | if (!ret) | ||
1060 | ret = si4713_set_mute(sdev, ctrl->val); | ||
1061 | if (!ret) | ||
1062 | ret = si4713_setup(sdev); | ||
1063 | if (ret) | ||
1064 | return ret; | ||
1065 | force = true; | ||
1507 | } | 1066 | } |
1508 | 1067 | ||
1509 | return 0; | 1068 | if (!sdev->power_state) |
1510 | } | 1069 | return 0; |
1511 | |||
1512 | /* si4713_g_ext_ctrls - get extended controls value */ | ||
1513 | static int si4713_g_ext_ctrls(struct v4l2_subdev *sd, | ||
1514 | struct v4l2_ext_controls *ctrls) | ||
1515 | { | ||
1516 | struct si4713_device *sdev = to_si4713_device(sd); | ||
1517 | int i; | ||
1518 | 1070 | ||
1519 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) | 1071 | for (c = 1; !ret && c < ctrl->ncontrols; c++) { |
1520 | return -EINVAL; | 1072 | ctrl = ctrl->cluster[c]; |
1521 | 1073 | ||
1522 | for (i = 0; i < ctrls->count; i++) { | 1074 | if (!force && !ctrl->is_new) |
1523 | int err; | 1075 | continue; |
1524 | 1076 | ||
1525 | switch ((ctrls->controls + i)->id) { | 1077 | switch (ctrl->id) { |
1526 | case V4L2_CID_RDS_TX_PS_NAME: | 1078 | case V4L2_CID_RDS_TX_PS_NAME: |
1079 | ret = si4713_set_rds_ps_name(sdev, ctrl->string); | ||
1080 | break; | ||
1081 | |||
1527 | case V4L2_CID_RDS_TX_RADIO_TEXT: | 1082 | case V4L2_CID_RDS_TX_RADIO_TEXT: |
1528 | err = si4713_read_econtrol_string(sdev, | 1083 | ret = si4713_set_rds_radio_text(sdev, ctrl->string); |
1529 | ctrls->controls + i); | ||
1530 | break; | 1084 | break; |
1085 | |||
1531 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | 1086 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: |
1087 | /* don't handle this control if we force setting all | ||
1088 | * controls since in that case it will be handled by | ||
1089 | * V4L2_CID_TUNE_POWER_LEVEL. */ | ||
1090 | if (force) | ||
1091 | break; | ||
1092 | /* fall through */ | ||
1532 | case V4L2_CID_TUNE_POWER_LEVEL: | 1093 | case V4L2_CID_TUNE_POWER_LEVEL: |
1533 | err = si4713_read_econtrol_tune(sdev, | 1094 | ret = si4713_tx_tune_power(sdev, |
1534 | ctrls->controls + i); | 1095 | sdev->tune_pwr_level->val, sdev->tune_ant_cap->val); |
1096 | if (!ret) { | ||
1097 | /* Make sure we don't set this twice */ | ||
1098 | sdev->tune_ant_cap->is_new = false; | ||
1099 | sdev->tune_pwr_level->is_new = false; | ||
1100 | } | ||
1535 | break; | 1101 | break; |
1536 | default: | ||
1537 | err = si4713_read_econtrol_integers(sdev, | ||
1538 | ctrls->controls + i); | ||
1539 | } | ||
1540 | |||
1541 | if (err < 0) { | ||
1542 | ctrls->error_idx = i; | ||
1543 | return err; | ||
1544 | } | ||
1545 | } | ||
1546 | |||
1547 | return 0; | ||
1548 | } | ||
1549 | |||
1550 | /* si4713_queryctrl - enumerate control items */ | ||
1551 | static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | ||
1552 | { | ||
1553 | int rval = 0; | ||
1554 | |||
1555 | switch (qc->id) { | ||
1556 | /* User class controls */ | ||
1557 | case V4L2_CID_AUDIO_MUTE: | ||
1558 | rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, DEFAULT_MUTE); | ||
1559 | break; | ||
1560 | /* FM_TX class controls */ | ||
1561 | case V4L2_CID_RDS_TX_PI: | ||
1562 | rval = v4l2_ctrl_query_fill(qc, 0, 0xFFFF, 1, DEFAULT_RDS_PI); | ||
1563 | break; | ||
1564 | case V4L2_CID_RDS_TX_PTY: | ||
1565 | rval = v4l2_ctrl_query_fill(qc, 0, 31, 1, DEFAULT_RDS_PTY); | ||
1566 | break; | ||
1567 | case V4L2_CID_RDS_TX_DEVIATION: | ||
1568 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_DEVIATION, | ||
1569 | 10, DEFAULT_RDS_DEVIATION); | ||
1570 | break; | ||
1571 | case V4L2_CID_RDS_TX_PS_NAME: | ||
1572 | /* | ||
1573 | * Report step as 8. From RDS spec, psname | ||
1574 | * should be 8. But there are receivers which scroll strings | ||
1575 | * sized as 8xN. | ||
1576 | */ | ||
1577 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_PS_NAME, 8, 0); | ||
1578 | break; | ||
1579 | case V4L2_CID_RDS_TX_RADIO_TEXT: | ||
1580 | /* | ||
1581 | * Report step as 32 (2A block). From RDS spec, | ||
1582 | * radio text should be 32 for 2A block. But there are receivers | ||
1583 | * which scroll strings sized as 32xN. Setting default to 32. | ||
1584 | */ | ||
1585 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_RADIO_TEXT, 32, 0); | ||
1586 | break; | ||
1587 | 1102 | ||
1588 | case V4L2_CID_AUDIO_LIMITER_ENABLED: | 1103 | default: |
1589 | rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); | 1104 | ret = si4713_choose_econtrol_action(sdev, ctrl->id, &bit, |
1590 | break; | 1105 | &mask, &property, &mul, &table, &size); |
1591 | case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: | 1106 | if (ret < 0) |
1592 | rval = v4l2_ctrl_query_fill(qc, 250, MAX_LIMITER_RELEASE_TIME, | 1107 | break; |
1593 | 50, DEFAULT_LIMITER_RTIME); | 1108 | |
1594 | break; | 1109 | val = ctrl->val; |
1595 | case V4L2_CID_AUDIO_LIMITER_DEVIATION: | 1110 | if (mul) { |
1596 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_LIMITER_DEVIATION, | 1111 | val = val / mul; |
1597 | 10, DEFAULT_LIMITER_DEV); | 1112 | } else if (table) { |
1598 | break; | 1113 | ret = usecs_to_dev(val, table, size); |
1599 | 1114 | if (ret < 0) | |
1600 | case V4L2_CID_AUDIO_COMPRESSION_ENABLED: | 1115 | break; |
1601 | rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); | 1116 | val = ret; |
1602 | break; | 1117 | ret = 0; |
1603 | case V4L2_CID_AUDIO_COMPRESSION_GAIN: | 1118 | } |
1604 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_GAIN, 1, | ||
1605 | DEFAULT_ACOMP_GAIN); | ||
1606 | break; | ||
1607 | case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: | ||
1608 | rval = v4l2_ctrl_query_fill(qc, MIN_ACOMP_THRESHOLD, | ||
1609 | MAX_ACOMP_THRESHOLD, 1, | ||
1610 | DEFAULT_ACOMP_THRESHOLD); | ||
1611 | break; | ||
1612 | case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: | ||
1613 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_ATTACK_TIME, | ||
1614 | 500, DEFAULT_ACOMP_ATIME); | ||
1615 | break; | ||
1616 | case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: | ||
1617 | rval = v4l2_ctrl_query_fill(qc, 100000, MAX_ACOMP_RELEASE_TIME, | ||
1618 | 100000, DEFAULT_ACOMP_RTIME); | ||
1619 | break; | ||
1620 | |||
1621 | case V4L2_CID_PILOT_TONE_ENABLED: | ||
1622 | rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); | ||
1623 | break; | ||
1624 | case V4L2_CID_PILOT_TONE_DEVIATION: | ||
1625 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_DEVIATION, | ||
1626 | 10, DEFAULT_PILOT_DEVIATION); | ||
1627 | break; | ||
1628 | case V4L2_CID_PILOT_TONE_FREQUENCY: | ||
1629 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_FREQUENCY, | ||
1630 | 1, DEFAULT_PILOT_FREQUENCY); | ||
1631 | break; | ||
1632 | |||
1633 | case V4L2_CID_TUNE_PREEMPHASIS: | ||
1634 | rval = v4l2_ctrl_query_fill(qc, V4L2_PREEMPHASIS_DISABLED, | ||
1635 | V4L2_PREEMPHASIS_75_uS, 1, | ||
1636 | V4L2_PREEMPHASIS_50_uS); | ||
1637 | break; | ||
1638 | case V4L2_CID_TUNE_POWER_LEVEL: | ||
1639 | rval = v4l2_ctrl_query_fill(qc, 0, 120, 1, DEFAULT_POWER_LEVEL); | ||
1640 | break; | ||
1641 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | ||
1642 | rval = v4l2_ctrl_query_fill(qc, 0, 191, 1, 0); | ||
1643 | break; | ||
1644 | default: | ||
1645 | rval = -EINVAL; | ||
1646 | break; | ||
1647 | } | ||
1648 | |||
1649 | return rval; | ||
1650 | } | ||
1651 | |||
1652 | /* si4713_g_ctrl - get the value of a control */ | ||
1653 | static int si4713_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
1654 | { | ||
1655 | struct si4713_device *sdev = to_si4713_device(sd); | ||
1656 | int rval = 0; | ||
1657 | |||
1658 | if (!sdev) | ||
1659 | return -ENODEV; | ||
1660 | |||
1661 | if (sdev->power_state) { | ||
1662 | rval = si4713_read_property(sdev, SI4713_TX_LINE_INPUT_MUTE, | ||
1663 | &sdev->mute); | ||
1664 | |||
1665 | if (rval < 0) | ||
1666 | return rval; | ||
1667 | } | ||
1668 | |||
1669 | switch (ctrl->id) { | ||
1670 | case V4L2_CID_AUDIO_MUTE: | ||
1671 | ctrl->value = get_mute(sdev->mute); | ||
1672 | break; | ||
1673 | } | ||
1674 | |||
1675 | return rval; | ||
1676 | } | ||
1677 | |||
1678 | /* si4713_s_ctrl - set the value of a control */ | ||
1679 | static int si4713_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
1680 | { | ||
1681 | struct si4713_device *sdev = to_si4713_device(sd); | ||
1682 | int rval = 0; | ||
1683 | |||
1684 | if (!sdev) | ||
1685 | return -ENODEV; | ||
1686 | |||
1687 | switch (ctrl->id) { | ||
1688 | case V4L2_CID_AUDIO_MUTE: | ||
1689 | if (ctrl->value) { | ||
1690 | rval = si4713_set_mute(sdev, ctrl->value); | ||
1691 | if (rval < 0) | ||
1692 | goto exit; | ||
1693 | |||
1694 | rval = si4713_set_power_state(sdev, POWER_DOWN); | ||
1695 | } else { | ||
1696 | rval = si4713_set_power_state(sdev, POWER_UP); | ||
1697 | if (rval < 0) | ||
1698 | goto exit; | ||
1699 | 1119 | ||
1700 | rval = si4713_setup(sdev); | 1120 | if (mask) { |
1701 | if (rval < 0) | 1121 | ret = si4713_read_property(sdev, property, &val); |
1702 | goto exit; | 1122 | if (ret < 0) |
1123 | break; | ||
1124 | val = set_bits(val, ctrl->val, bit, mask); | ||
1125 | } | ||
1703 | 1126 | ||
1704 | rval = si4713_set_mute(sdev, ctrl->value); | 1127 | ret = si4713_write_property(sdev, property, val); |
1128 | if (ret < 0) | ||
1129 | break; | ||
1130 | if (mask) | ||
1131 | val = ctrl->val; | ||
1132 | break; | ||
1705 | } | 1133 | } |
1706 | break; | ||
1707 | } | 1134 | } |
1708 | 1135 | ||
1709 | exit: | 1136 | return ret; |
1710 | return rval; | ||
1711 | } | 1137 | } |
1712 | 1138 | ||
1713 | /* si4713_ioctl - deal with private ioctls (only rnl for now) */ | 1139 | /* si4713_ioctl - deal with private ioctls (only rnl for now) */ |
@@ -1746,15 +1172,6 @@ static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) | |||
1746 | return rval; | 1172 | return rval; |
1747 | } | 1173 | } |
1748 | 1174 | ||
1749 | static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = { | ||
1750 | .queryctrl = si4713_queryctrl, | ||
1751 | .g_ext_ctrls = si4713_g_ext_ctrls, | ||
1752 | .s_ext_ctrls = si4713_s_ext_ctrls, | ||
1753 | .g_ctrl = si4713_g_ctrl, | ||
1754 | .s_ctrl = si4713_s_ctrl, | ||
1755 | .ioctl = si4713_ioctl, | ||
1756 | }; | ||
1757 | |||
1758 | /* si4713_g_modulator - get modulator attributes */ | 1175 | /* si4713_g_modulator - get modulator attributes */ |
1759 | static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) | 1176 | static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) |
1760 | { | 1177 | { |
@@ -1784,7 +1201,6 @@ static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) | |||
1784 | return rval; | 1201 | return rval; |
1785 | 1202 | ||
1786 | sdev->stereo = get_status_bit(comp_en, 1, 1 << 1); | 1203 | sdev->stereo = get_status_bit(comp_en, 1, 1 << 1); |
1787 | sdev->rds_info.enabled = get_status_bit(comp_en, 2, 1 << 2); | ||
1788 | } | 1204 | } |
1789 | 1205 | ||
1790 | /* Report current audio mode: mono or stereo */ | 1206 | /* Report current audio mode: mono or stereo */ |
@@ -1794,7 +1210,7 @@ static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) | |||
1794 | vm->txsubchans = V4L2_TUNER_SUB_MONO; | 1210 | vm->txsubchans = V4L2_TUNER_SUB_MONO; |
1795 | 1211 | ||
1796 | /* Report rds feature status */ | 1212 | /* Report rds feature status */ |
1797 | if (sdev->rds_info.enabled) | 1213 | if (sdev->rds_enabled) |
1798 | vm->txsubchans |= V4L2_TUNER_SUB_RDS; | 1214 | vm->txsubchans |= V4L2_TUNER_SUB_RDS; |
1799 | else | 1215 | else |
1800 | vm->txsubchans &= ~V4L2_TUNER_SUB_RDS; | 1216 | vm->txsubchans &= ~V4L2_TUNER_SUB_RDS; |
@@ -1842,7 +1258,7 @@ static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulato | |||
1842 | } | 1258 | } |
1843 | 1259 | ||
1844 | sdev->stereo = stereo; | 1260 | sdev->stereo = stereo; |
1845 | sdev->rds_info.enabled = rds; | 1261 | sdev->rds_enabled = rds; |
1846 | 1262 | ||
1847 | return rval; | 1263 | return rval; |
1848 | } | 1264 | } |
@@ -1897,6 +1313,14 @@ static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequenc | |||
1897 | return rval; | 1313 | return rval; |
1898 | } | 1314 | } |
1899 | 1315 | ||
1316 | static const struct v4l2_ctrl_ops si4713_ctrl_ops = { | ||
1317 | .s_ctrl = si4713_s_ctrl, | ||
1318 | }; | ||
1319 | |||
1320 | static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = { | ||
1321 | .ioctl = si4713_ioctl, | ||
1322 | }; | ||
1323 | |||
1900 | static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = { | 1324 | static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = { |
1901 | .g_frequency = si4713_g_frequency, | 1325 | .g_frequency = si4713_g_frequency, |
1902 | .s_frequency = si4713_s_frequency, | 1326 | .s_frequency = si4713_s_frequency, |
@@ -1918,6 +1342,7 @@ static int si4713_probe(struct i2c_client *client, | |||
1918 | { | 1342 | { |
1919 | struct si4713_device *sdev; | 1343 | struct si4713_device *sdev; |
1920 | struct si4713_platform_data *pdata = client->dev.platform_data; | 1344 | struct si4713_platform_data *pdata = client->dev.platform_data; |
1345 | struct v4l2_ctrl_handler *hdl; | ||
1921 | int rval, i; | 1346 | int rval, i; |
1922 | 1347 | ||
1923 | sdev = kzalloc(sizeof *sdev, GFP_KERNEL); | 1348 | sdev = kzalloc(sizeof *sdev, GFP_KERNEL); |
@@ -1953,6 +1378,82 @@ static int si4713_probe(struct i2c_client *client, | |||
1953 | 1378 | ||
1954 | init_completion(&sdev->work); | 1379 | init_completion(&sdev->work); |
1955 | 1380 | ||
1381 | hdl = &sdev->ctrl_handler; | ||
1382 | v4l2_ctrl_handler_init(hdl, 20); | ||
1383 | sdev->mute = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1384 | V4L2_CID_AUDIO_MUTE, 0, 1, 1, DEFAULT_MUTE); | ||
1385 | |||
1386 | sdev->rds_pi = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1387 | V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI); | ||
1388 | sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1389 | V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY); | ||
1390 | sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1391 | V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION, | ||
1392 | 10, DEFAULT_RDS_DEVIATION); | ||
1393 | /* | ||
1394 | * Report step as 8. From RDS spec, psname | ||
1395 | * should be 8. But there are receivers which scroll strings | ||
1396 | * sized as 8xN. | ||
1397 | */ | ||
1398 | sdev->rds_ps_name = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1399 | V4L2_CID_RDS_TX_PS_NAME, 0, MAX_RDS_PS_NAME, 8, 0); | ||
1400 | /* | ||
1401 | * Report step as 32 (2A block). From RDS spec, | ||
1402 | * radio text should be 32 for 2A block. But there are receivers | ||
1403 | * which scroll strings sized as 32xN. Setting default to 32. | ||
1404 | */ | ||
1405 | sdev->rds_radio_text = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1406 | V4L2_CID_RDS_TX_RADIO_TEXT, 0, MAX_RDS_RADIO_TEXT, 32, 0); | ||
1407 | |||
1408 | sdev->limiter_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1409 | V4L2_CID_AUDIO_LIMITER_ENABLED, 0, 1, 1, 1); | ||
1410 | sdev->limiter_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1411 | V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, 250, | ||
1412 | MAX_LIMITER_RELEASE_TIME, 10, DEFAULT_LIMITER_RTIME); | ||
1413 | sdev->limiter_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1414 | V4L2_CID_AUDIO_LIMITER_DEVIATION, 0, | ||
1415 | MAX_LIMITER_DEVIATION, 10, DEFAULT_LIMITER_DEV); | ||
1416 | |||
1417 | sdev->compression_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1418 | V4L2_CID_AUDIO_COMPRESSION_ENABLED, 0, 1, 1, 1); | ||
1419 | sdev->compression_gain = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1420 | V4L2_CID_AUDIO_COMPRESSION_GAIN, 0, MAX_ACOMP_GAIN, 1, | ||
1421 | DEFAULT_ACOMP_GAIN); | ||
1422 | sdev->compression_threshold = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1423 | V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, MIN_ACOMP_THRESHOLD, | ||
1424 | MAX_ACOMP_THRESHOLD, 1, | ||
1425 | DEFAULT_ACOMP_THRESHOLD); | ||
1426 | sdev->compression_attack_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1427 | V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, 0, | ||
1428 | MAX_ACOMP_ATTACK_TIME, 500, DEFAULT_ACOMP_ATIME); | ||
1429 | sdev->compression_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1430 | V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, 100000, | ||
1431 | MAX_ACOMP_RELEASE_TIME, 100000, DEFAULT_ACOMP_RTIME); | ||
1432 | |||
1433 | sdev->pilot_tone_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1434 | V4L2_CID_PILOT_TONE_ENABLED, 0, 1, 1, 1); | ||
1435 | sdev->pilot_tone_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1436 | V4L2_CID_PILOT_TONE_DEVIATION, 0, MAX_PILOT_DEVIATION, | ||
1437 | 10, DEFAULT_PILOT_DEVIATION); | ||
1438 | sdev->pilot_tone_freq = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1439 | V4L2_CID_PILOT_TONE_FREQUENCY, 0, MAX_PILOT_FREQUENCY, | ||
1440 | 1, DEFAULT_PILOT_FREQUENCY); | ||
1441 | |||
1442 | sdev->tune_preemphasis = v4l2_ctrl_new_std_menu(hdl, &si4713_ctrl_ops, | ||
1443 | V4L2_CID_TUNE_PREEMPHASIS, | ||
1444 | V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS); | ||
1445 | sdev->tune_pwr_level = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1446 | V4L2_CID_TUNE_POWER_LEVEL, 0, 120, 1, DEFAULT_POWER_LEVEL); | ||
1447 | sdev->tune_ant_cap = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, | ||
1448 | V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0, 191, 1, 0); | ||
1449 | |||
1450 | if (hdl->error) { | ||
1451 | rval = hdl->error; | ||
1452 | goto free_ctrls; | ||
1453 | } | ||
1454 | v4l2_ctrl_cluster(20, &sdev->mute); | ||
1455 | sdev->sd.ctrl_handler = hdl; | ||
1456 | |||
1956 | if (client->irq) { | 1457 | if (client->irq) { |
1957 | rval = request_irq(client->irq, | 1458 | rval = request_irq(client->irq, |
1958 | si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, | 1459 | si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, |
@@ -1977,6 +1478,8 @@ static int si4713_probe(struct i2c_client *client, | |||
1977 | free_irq: | 1478 | free_irq: |
1978 | if (client->irq) | 1479 | if (client->irq) |
1979 | free_irq(client->irq, sdev); | 1480 | free_irq(client->irq, sdev); |
1481 | free_ctrls: | ||
1482 | v4l2_ctrl_handler_free(hdl); | ||
1980 | put_reg: | 1483 | put_reg: |
1981 | regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); | 1484 | regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); |
1982 | free_gpio: | 1485 | free_gpio: |
@@ -2001,6 +1504,7 @@ static int si4713_remove(struct i2c_client *client) | |||
2001 | free_irq(client->irq, sdev); | 1504 | free_irq(client->irq, sdev); |
2002 | 1505 | ||
2003 | v4l2_device_unregister_subdev(sd); | 1506 | v4l2_device_unregister_subdev(sd); |
1507 | v4l2_ctrl_handler_free(sd->ctrl_handler); | ||
2004 | regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); | 1508 | regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); |
2005 | if (gpio_is_valid(sdev->gpio_reset)) | 1509 | if (gpio_is_valid(sdev->gpio_reset)) |
2006 | gpio_free(sdev->gpio_reset); | 1510 | gpio_free(sdev->gpio_reset); |
diff --git a/drivers/media/radio/si4713-i2c.h b/drivers/media/radio/si4713-i2c.h index 979828da9d27..25cdea26343b 100644 --- a/drivers/media/radio/si4713-i2c.h +++ b/drivers/media/radio/si4713-i2c.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #define SI4713_I2C_H | 16 | #define SI4713_I2C_H |
17 | 17 | ||
18 | #include <media/v4l2-subdev.h> | 18 | #include <media/v4l2-subdev.h> |
19 | #include <media/v4l2-ctrls.h> | ||
19 | #include <media/si4713.h> | 20 | #include <media/si4713.h> |
20 | 21 | ||
21 | #define SI4713_PRODUCT_NUMBER 0x0D | 22 | #define SI4713_PRODUCT_NUMBER 0x0D |
@@ -160,56 +161,33 @@ | |||
160 | #define POWER_UP 0x01 | 161 | #define POWER_UP 0x01 |
161 | #define POWER_DOWN 0x00 | 162 | #define POWER_DOWN 0x00 |
162 | 163 | ||
163 | struct rds_info { | ||
164 | u32 pi; | ||
165 | #define MAX_RDS_PTY 31 | 164 | #define MAX_RDS_PTY 31 |
166 | u32 pty; | ||
167 | #define MAX_RDS_DEVIATION 90000 | 165 | #define MAX_RDS_DEVIATION 90000 |
168 | u32 deviation; | 166 | |
169 | /* | 167 | /* |
170 | * PSNAME is known to be defined as 8 character sized (RDS Spec). | 168 | * PSNAME is known to be defined as 8 character sized (RDS Spec). |
171 | * However, there is receivers which scroll PSNAME 8xN sized. | 169 | * However, there is receivers which scroll PSNAME 8xN sized. |
172 | */ | 170 | */ |
173 | #define MAX_RDS_PS_NAME 96 | 171 | #define MAX_RDS_PS_NAME 96 |
174 | u8 ps_name[MAX_RDS_PS_NAME + 1]; | 172 | |
175 | /* | 173 | /* |
176 | * MAX_RDS_RADIO_TEXT is known to be defined as 32 (2A group) or 64 (2B group) | 174 | * MAX_RDS_RADIO_TEXT is known to be defined as 32 (2A group) or 64 (2B group) |
177 | * character sized (RDS Spec). | 175 | * character sized (RDS Spec). |
178 | * However, there is receivers which scroll them as well. | 176 | * However, there is receivers which scroll them as well. |
179 | */ | 177 | */ |
180 | #define MAX_RDS_RADIO_TEXT 384 | 178 | #define MAX_RDS_RADIO_TEXT 384 |
181 | u8 radio_text[MAX_RDS_RADIO_TEXT + 1]; | ||
182 | u32 enabled; | ||
183 | }; | ||
184 | 179 | ||
185 | struct limiter_info { | ||
186 | #define MAX_LIMITER_RELEASE_TIME 102390 | 180 | #define MAX_LIMITER_RELEASE_TIME 102390 |
187 | u32 release_time; | ||
188 | #define MAX_LIMITER_DEVIATION 90000 | 181 | #define MAX_LIMITER_DEVIATION 90000 |
189 | u32 deviation; | ||
190 | u32 enabled; | ||
191 | }; | ||
192 | 182 | ||
193 | struct pilot_info { | ||
194 | #define MAX_PILOT_DEVIATION 90000 | 183 | #define MAX_PILOT_DEVIATION 90000 |
195 | u32 deviation; | ||
196 | #define MAX_PILOT_FREQUENCY 19000 | 184 | #define MAX_PILOT_FREQUENCY 19000 |
197 | u32 frequency; | ||
198 | u32 enabled; | ||
199 | }; | ||
200 | 185 | ||
201 | struct acomp_info { | ||
202 | #define MAX_ACOMP_RELEASE_TIME 1000000 | 186 | #define MAX_ACOMP_RELEASE_TIME 1000000 |
203 | u32 release_time; | ||
204 | #define MAX_ACOMP_ATTACK_TIME 5000 | 187 | #define MAX_ACOMP_ATTACK_TIME 5000 |
205 | u32 attack_time; | ||
206 | #define MAX_ACOMP_THRESHOLD 0 | 188 | #define MAX_ACOMP_THRESHOLD 0 |
207 | #define MIN_ACOMP_THRESHOLD (-40) | 189 | #define MIN_ACOMP_THRESHOLD (-40) |
208 | s32 threshold; | ||
209 | #define MAX_ACOMP_GAIN 20 | 190 | #define MAX_ACOMP_GAIN 20 |
210 | u32 gain; | ||
211 | u32 enabled; | ||
212 | }; | ||
213 | 191 | ||
214 | #define SI4713_NUM_SUPPLIES 2 | 192 | #define SI4713_NUM_SUPPLIES 2 |
215 | 193 | ||
@@ -219,20 +197,41 @@ struct acomp_info { | |||
219 | struct si4713_device { | 197 | struct si4713_device { |
220 | /* v4l2_subdev and i2c reference (v4l2_subdev priv data) */ | 198 | /* v4l2_subdev and i2c reference (v4l2_subdev priv data) */ |
221 | struct v4l2_subdev sd; | 199 | struct v4l2_subdev sd; |
200 | struct v4l2_ctrl_handler ctrl_handler; | ||
222 | /* private data structures */ | 201 | /* private data structures */ |
202 | struct { /* si4713 control cluster */ | ||
203 | /* This is one big cluster since the mute control | ||
204 | * powers off the device and after unmuting again all | ||
205 | * controls need to be set at once. The only way of doing | ||
206 | * that is by making it one big cluster. */ | ||
207 | struct v4l2_ctrl *mute; | ||
208 | struct v4l2_ctrl *rds_ps_name; | ||
209 | struct v4l2_ctrl *rds_radio_text; | ||
210 | struct v4l2_ctrl *rds_pi; | ||
211 | struct v4l2_ctrl *rds_deviation; | ||
212 | struct v4l2_ctrl *rds_pty; | ||
213 | struct v4l2_ctrl *compression_enabled; | ||
214 | struct v4l2_ctrl *compression_threshold; | ||
215 | struct v4l2_ctrl *compression_gain; | ||
216 | struct v4l2_ctrl *compression_attack_time; | ||
217 | struct v4l2_ctrl *compression_release_time; | ||
218 | struct v4l2_ctrl *pilot_tone_enabled; | ||
219 | struct v4l2_ctrl *pilot_tone_freq; | ||
220 | struct v4l2_ctrl *pilot_tone_deviation; | ||
221 | struct v4l2_ctrl *limiter_enabled; | ||
222 | struct v4l2_ctrl *limiter_deviation; | ||
223 | struct v4l2_ctrl *limiter_release_time; | ||
224 | struct v4l2_ctrl *tune_preemphasis; | ||
225 | struct v4l2_ctrl *tune_pwr_level; | ||
226 | struct v4l2_ctrl *tune_ant_cap; | ||
227 | }; | ||
223 | struct completion work; | 228 | struct completion work; |
224 | struct rds_info rds_info; | ||
225 | struct limiter_info limiter_info; | ||
226 | struct pilot_info pilot_info; | ||
227 | struct acomp_info acomp_info; | ||
228 | struct regulator_bulk_data supplies[SI4713_NUM_SUPPLIES]; | 229 | struct regulator_bulk_data supplies[SI4713_NUM_SUPPLIES]; |
229 | int gpio_reset; | 230 | int gpio_reset; |
231 | u32 power_state; | ||
232 | u32 rds_enabled; | ||
230 | u32 frequency; | 233 | u32 frequency; |
231 | u32 preemphasis; | 234 | u32 preemphasis; |
232 | u32 mute; | ||
233 | u32 power_level; | ||
234 | u32 power_state; | ||
235 | u32 antenna_capacitor; | ||
236 | u32 stereo; | 235 | u32 stereo; |
237 | u32 tune_rnl; | 236 | u32 tune_rnl; |
238 | }; | 237 | }; |