diff options
Diffstat (limited to 'drivers/media/radio/si4713-i2c.c')
-rw-r--r-- | drivers/media/radio/si4713-i2c.c | 1049 |
1 files changed, 236 insertions, 813 deletions
diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c index bd61b3bd0ca3..fe160882ee10 100644 --- a/drivers/media/radio/si4713-i2c.c +++ b/drivers/media/radio/si4713-i2c.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/mutex.h> | ||
25 | #include <linux/completion.h> | 24 | #include <linux/completion.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
@@ -53,8 +52,6 @@ static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = { | |||
53 | 52 | ||
54 | #define DEFAULT_RDS_PI 0x00 | 53 | #define DEFAULT_RDS_PI 0x00 |
55 | #define DEFAULT_RDS_PTY 0x00 | 54 | #define DEFAULT_RDS_PTY 0x00 |
56 | #define DEFAULT_RDS_PS_NAME "" | ||
57 | #define DEFAULT_RDS_RADIO_TEXT DEFAULT_RDS_PS_NAME | ||
58 | #define DEFAULT_RDS_DEVIATION 0x00C8 | 55 | #define DEFAULT_RDS_DEVIATION 0x00C8 |
59 | #define DEFAULT_RDS_PS_REPEAT_COUNT 0x0003 | 56 | #define DEFAULT_RDS_PS_REPEAT_COUNT 0x0003 |
60 | #define DEFAULT_LIMITER_RTIME 0x1392 | 57 | #define DEFAULT_LIMITER_RTIME 0x1392 |
@@ -108,7 +105,6 @@ static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = { | |||
108 | (status & SI4713_ERR)) | 105 | (status & SI4713_ERR)) |
109 | /* mute definition */ | 106 | /* mute definition */ |
110 | #define set_mute(p) ((p & 1) | ((p & 1) << 1)); | 107 | #define set_mute(p) ((p & 1) | ((p & 1) << 1)); |
111 | #define get_mute(p) (p & 0x01) | ||
112 | 108 | ||
113 | #ifdef DEBUG | 109 | #ifdef DEBUG |
114 | #define DBG_BUFFER(device, message, buffer, size) \ | 110 | #define DBG_BUFFER(device, message, buffer, size) \ |
@@ -190,21 +186,6 @@ static int usecs_to_dev(unsigned long usecs, unsigned long const array[], | |||
190 | return rval; | 186 | return rval; |
191 | } | 187 | } |
192 | 188 | ||
193 | static unsigned long dev_to_usecs(int value, unsigned long const array[], | ||
194 | int size) | ||
195 | { | ||
196 | int i; | ||
197 | int rval = -EINVAL; | ||
198 | |||
199 | for (i = 0; i < size / 2; i++) | ||
200 | if (array[i * 2] == value) { | ||
201 | rval = array[(i * 2) + 1]; | ||
202 | break; | ||
203 | } | ||
204 | |||
205 | return rval; | ||
206 | } | ||
207 | |||
208 | /* si4713_handler: IRQ handler, just complete work */ | 189 | /* si4713_handler: IRQ handler, just complete work */ |
209 | static irqreturn_t si4713_handler(int irq, void *dev) | 190 | static irqreturn_t si4713_handler(int irq, void *dev) |
210 | { | 191 | { |
@@ -458,15 +439,13 @@ static int si4713_checkrev(struct si4713_device *sdev) | |||
458 | int rval; | 439 | int rval; |
459 | u8 resp[SI4713_GETREV_NRESP]; | 440 | u8 resp[SI4713_GETREV_NRESP]; |
460 | 441 | ||
461 | mutex_lock(&sdev->mutex); | ||
462 | |||
463 | rval = si4713_send_command(sdev, SI4713_CMD_GET_REV, | 442 | rval = si4713_send_command(sdev, SI4713_CMD_GET_REV, |
464 | NULL, 0, | 443 | NULL, 0, |
465 | resp, ARRAY_SIZE(resp), | 444 | resp, ARRAY_SIZE(resp), |
466 | DEFAULT_TIMEOUT); | 445 | DEFAULT_TIMEOUT); |
467 | 446 | ||
468 | if (rval < 0) | 447 | if (rval < 0) |
469 | goto unlock; | 448 | return rval; |
470 | 449 | ||
471 | if (resp[1] == SI4713_PRODUCT_NUMBER) { | 450 | if (resp[1] == SI4713_PRODUCT_NUMBER) { |
472 | v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n", | 451 | v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n", |
@@ -475,9 +454,6 @@ static int si4713_checkrev(struct si4713_device *sdev) | |||
475 | v4l2_err(&sdev->sd, "Invalid product number\n"); | 454 | v4l2_err(&sdev->sd, "Invalid product number\n"); |
476 | rval = -EINVAL; | 455 | rval = -EINVAL; |
477 | } | 456 | } |
478 | |||
479 | unlock: | ||
480 | mutex_unlock(&sdev->mutex); | ||
481 | return rval; | 457 | return rval; |
482 | } | 458 | } |
483 | 459 | ||
@@ -778,17 +754,9 @@ static int si4713_tx_rds_ps(struct si4713_device *sdev, u8 psid, | |||
778 | 754 | ||
779 | static int si4713_set_power_state(struct si4713_device *sdev, u8 value) | 755 | static int si4713_set_power_state(struct si4713_device *sdev, u8 value) |
780 | { | 756 | { |
781 | int rval; | ||
782 | |||
783 | mutex_lock(&sdev->mutex); | ||
784 | |||
785 | if (value) | 757 | if (value) |
786 | rval = si4713_powerup(sdev); | 758 | return si4713_powerup(sdev); |
787 | else | 759 | return si4713_powerdown(sdev); |
788 | rval = si4713_powerdown(sdev); | ||
789 | |||
790 | mutex_unlock(&sdev->mutex); | ||
791 | return rval; | ||
792 | } | 760 | } |
793 | 761 | ||
794 | static int si4713_set_mute(struct si4713_device *sdev, u16 mute) | 762 | static int si4713_set_mute(struct si4713_device *sdev, u16 mute) |
@@ -797,17 +765,10 @@ static int si4713_set_mute(struct si4713_device *sdev, u16 mute) | |||
797 | 765 | ||
798 | mute = set_mute(mute); | 766 | mute = set_mute(mute); |
799 | 767 | ||
800 | mutex_lock(&sdev->mutex); | ||
801 | |||
802 | if (sdev->power_state) | 768 | if (sdev->power_state) |
803 | rval = si4713_write_property(sdev, | 769 | rval = si4713_write_property(sdev, |
804 | SI4713_TX_LINE_INPUT_MUTE, mute); | 770 | SI4713_TX_LINE_INPUT_MUTE, mute); |
805 | 771 | ||
806 | if (rval >= 0) | ||
807 | sdev->mute = get_mute(mute); | ||
808 | |||
809 | mutex_unlock(&sdev->mutex); | ||
810 | |||
811 | return rval; | 772 | return rval; |
812 | } | 773 | } |
813 | 774 | ||
@@ -820,15 +781,13 @@ static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name) | |||
820 | if (!strlen(ps_name)) | 781 | if (!strlen(ps_name)) |
821 | memset(ps_name, 0, MAX_RDS_PS_NAME + 1); | 782 | memset(ps_name, 0, MAX_RDS_PS_NAME + 1); |
822 | 783 | ||
823 | mutex_lock(&sdev->mutex); | ||
824 | |||
825 | if (sdev->power_state) { | 784 | if (sdev->power_state) { |
826 | /* Write the new ps name and clear the padding */ | 785 | /* Write the new ps name and clear the padding */ |
827 | for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) { | 786 | for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) { |
828 | rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)), | 787 | rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)), |
829 | ps_name + i); | 788 | ps_name + i); |
830 | if (rval < 0) | 789 | if (rval < 0) |
831 | goto unlock; | 790 | return rval; |
832 | } | 791 | } |
833 | 792 | ||
834 | /* Setup the size to be sent */ | 793 | /* Setup the size to be sent */ |
@@ -841,19 +800,15 @@ static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name) | |||
841 | SI4713_TX_RDS_PS_MESSAGE_COUNT, | 800 | SI4713_TX_RDS_PS_MESSAGE_COUNT, |
842 | rds_ps_nblocks(len)); | 801 | rds_ps_nblocks(len)); |
843 | if (rval < 0) | 802 | if (rval < 0) |
844 | goto unlock; | 803 | return rval; |
845 | 804 | ||
846 | rval = si4713_write_property(sdev, | 805 | rval = si4713_write_property(sdev, |
847 | SI4713_TX_RDS_PS_REPEAT_COUNT, | 806 | SI4713_TX_RDS_PS_REPEAT_COUNT, |
848 | DEFAULT_RDS_PS_REPEAT_COUNT * 2); | 807 | DEFAULT_RDS_PS_REPEAT_COUNT * 2); |
849 | if (rval < 0) | 808 | if (rval < 0) |
850 | goto unlock; | 809 | return rval; |
851 | } | 810 | } |
852 | 811 | ||
853 | strncpy(sdev->rds_info.ps_name, ps_name, MAX_RDS_PS_NAME); | ||
854 | |||
855 | unlock: | ||
856 | mutex_unlock(&sdev->mutex); | ||
857 | return rval; | 812 | return rval; |
858 | } | 813 | } |
859 | 814 | ||
@@ -864,27 +819,24 @@ static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt) | |||
864 | u8 b_index = 0, cr_inserted = 0; | 819 | u8 b_index = 0, cr_inserted = 0; |
865 | s8 left; | 820 | s8 left; |
866 | 821 | ||
867 | mutex_lock(&sdev->mutex); | ||
868 | |||
869 | if (!sdev->power_state) | 822 | if (!sdev->power_state) |
870 | goto copy; | 823 | return rval; |
871 | 824 | ||
872 | 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); |
873 | if (rval < 0) | 826 | if (rval < 0) |
874 | goto unlock; | 827 | return rval; |
875 | 828 | ||
876 | if (!strlen(rt)) | 829 | if (!strlen(rt)) |
877 | goto copy; | 830 | return rval; |
878 | 831 | ||
879 | do { | 832 | do { |
880 | /* RDS spec says that if the last block isn't used, | 833 | /* RDS spec says that if the last block isn't used, |
881 | * then apply a carriage return | 834 | * then apply a carriage return |
882 | */ | 835 | */ |
883 | if (t_index < (RDS_RADIOTEXT_INDEX_MAX * | 836 | if (t_index < (RDS_RADIOTEXT_INDEX_MAX * RDS_RADIOTEXT_BLK_SIZE)) { |
884 | RDS_RADIOTEXT_BLK_SIZE)) { | ||
885 | for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) { | 837 | for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) { |
886 | if (!rt[t_index + i] || rt[t_index + i] == | 838 | if (!rt[t_index + i] || |
887 | RDS_CARRIAGE_RETURN) { | 839 | rt[t_index + i] == RDS_CARRIAGE_RETURN) { |
888 | rt[t_index + i] = RDS_CARRIAGE_RETURN; | 840 | rt[t_index + i] = RDS_CARRIAGE_RETURN; |
889 | cr_inserted = 1; | 841 | cr_inserted = 1; |
890 | break; | 842 | break; |
@@ -898,7 +850,7 @@ static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt) | |||
898 | compose_u16(rt[t_index + 2], rt[t_index + 3]), | 850 | compose_u16(rt[t_index + 2], rt[t_index + 3]), |
899 | &left); | 851 | &left); |
900 | if (rval < 0) | 852 | if (rval < 0) |
901 | goto unlock; | 853 | return rval; |
902 | 854 | ||
903 | t_index += RDS_RADIOTEXT_BLK_SIZE; | 855 | t_index += RDS_RADIOTEXT_BLK_SIZE; |
904 | 856 | ||
@@ -906,16 +858,38 @@ static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt) | |||
906 | break; | 858 | break; |
907 | } while (left > 0); | 859 | } while (left > 0); |
908 | 860 | ||
909 | copy: | 861 | return rval; |
910 | strncpy(sdev->rds_info.radio_text, rt, MAX_RDS_RADIO_TEXT); | 862 | } |
911 | 863 | ||
912 | unlock: | 864 | /* |
913 | mutex_unlock(&sdev->mutex); | 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: | ||
914 | return rval; | 888 | return rval; |
915 | } | 889 | } |
916 | 890 | ||
917 | 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, |
918 | u32 **shadow, s32 *bit, s32 *mask, u16 *property, int *mul, | 892 | s32 *bit, s32 *mask, u16 *property, int *mul, |
919 | unsigned long **table, int *size) | 893 | unsigned long **table, int *size) |
920 | { | 894 | { |
921 | s32 rval = 0; | 895 | s32 rval = 0; |
@@ -925,157 +899,71 @@ static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id, | |||
925 | case V4L2_CID_RDS_TX_PI: | 899 | case V4L2_CID_RDS_TX_PI: |
926 | *property = SI4713_TX_RDS_PI; | 900 | *property = SI4713_TX_RDS_PI; |
927 | *mul = 1; | 901 | *mul = 1; |
928 | *shadow = &sdev->rds_info.pi; | ||
929 | break; | 902 | break; |
930 | case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: | 903 | case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: |
931 | *property = SI4713_TX_ACOMP_THRESHOLD; | 904 | *property = SI4713_TX_ACOMP_THRESHOLD; |
932 | *mul = 1; | 905 | *mul = 1; |
933 | *shadow = &sdev->acomp_info.threshold; | ||
934 | break; | 906 | break; |
935 | case V4L2_CID_AUDIO_COMPRESSION_GAIN: | 907 | case V4L2_CID_AUDIO_COMPRESSION_GAIN: |
936 | *property = SI4713_TX_ACOMP_GAIN; | 908 | *property = SI4713_TX_ACOMP_GAIN; |
937 | *mul = 1; | 909 | *mul = 1; |
938 | *shadow = &sdev->acomp_info.gain; | ||
939 | break; | 910 | break; |
940 | case V4L2_CID_PILOT_TONE_FREQUENCY: | 911 | case V4L2_CID_PILOT_TONE_FREQUENCY: |
941 | *property = SI4713_TX_PILOT_FREQUENCY; | 912 | *property = SI4713_TX_PILOT_FREQUENCY; |
942 | *mul = 1; | 913 | *mul = 1; |
943 | *shadow = &sdev->pilot_info.frequency; | ||
944 | break; | 914 | break; |
945 | case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: | 915 | case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: |
946 | *property = SI4713_TX_ACOMP_ATTACK_TIME; | 916 | *property = SI4713_TX_ACOMP_ATTACK_TIME; |
947 | *mul = ATTACK_TIME_UNIT; | 917 | *mul = ATTACK_TIME_UNIT; |
948 | *shadow = &sdev->acomp_info.attack_time; | ||
949 | break; | 918 | break; |
950 | case V4L2_CID_PILOT_TONE_DEVIATION: | 919 | case V4L2_CID_PILOT_TONE_DEVIATION: |
951 | *property = SI4713_TX_PILOT_DEVIATION; | 920 | *property = SI4713_TX_PILOT_DEVIATION; |
952 | *mul = 10; | 921 | *mul = 10; |
953 | *shadow = &sdev->pilot_info.deviation; | ||
954 | break; | 922 | break; |
955 | case V4L2_CID_AUDIO_LIMITER_DEVIATION: | 923 | case V4L2_CID_AUDIO_LIMITER_DEVIATION: |
956 | *property = SI4713_TX_AUDIO_DEVIATION; | 924 | *property = SI4713_TX_AUDIO_DEVIATION; |
957 | *mul = 10; | 925 | *mul = 10; |
958 | *shadow = &sdev->limiter_info.deviation; | ||
959 | break; | 926 | break; |
960 | case V4L2_CID_RDS_TX_DEVIATION: | 927 | case V4L2_CID_RDS_TX_DEVIATION: |
961 | *property = SI4713_TX_RDS_DEVIATION; | 928 | *property = SI4713_TX_RDS_DEVIATION; |
962 | *mul = 1; | 929 | *mul = 1; |
963 | *shadow = &sdev->rds_info.deviation; | ||
964 | break; | 930 | break; |
965 | 931 | ||
966 | case V4L2_CID_RDS_TX_PTY: | 932 | case V4L2_CID_RDS_TX_PTY: |
967 | *property = SI4713_TX_RDS_PS_MISC; | 933 | *property = SI4713_TX_RDS_PS_MISC; |
968 | *bit = 5; | 934 | *bit = 5; |
969 | *mask = 0x1F << 5; | 935 | *mask = 0x1F << 5; |
970 | *shadow = &sdev->rds_info.pty; | ||
971 | break; | 936 | break; |
972 | case V4L2_CID_AUDIO_LIMITER_ENABLED: | 937 | case V4L2_CID_AUDIO_LIMITER_ENABLED: |
973 | *property = SI4713_TX_ACOMP_ENABLE; | 938 | *property = SI4713_TX_ACOMP_ENABLE; |
974 | *bit = 1; | 939 | *bit = 1; |
975 | *mask = 1 << 1; | 940 | *mask = 1 << 1; |
976 | *shadow = &sdev->limiter_info.enabled; | ||
977 | break; | 941 | break; |
978 | case V4L2_CID_AUDIO_COMPRESSION_ENABLED: | 942 | case V4L2_CID_AUDIO_COMPRESSION_ENABLED: |
979 | *property = SI4713_TX_ACOMP_ENABLE; | 943 | *property = SI4713_TX_ACOMP_ENABLE; |
980 | *bit = 0; | 944 | *bit = 0; |
981 | *mask = 1 << 0; | 945 | *mask = 1 << 0; |
982 | *shadow = &sdev->acomp_info.enabled; | ||
983 | break; | 946 | break; |
984 | case V4L2_CID_PILOT_TONE_ENABLED: | 947 | case V4L2_CID_PILOT_TONE_ENABLED: |
985 | *property = SI4713_TX_COMPONENT_ENABLE; | 948 | *property = SI4713_TX_COMPONENT_ENABLE; |
986 | *bit = 0; | 949 | *bit = 0; |
987 | *mask = 1 << 0; | 950 | *mask = 1 << 0; |
988 | *shadow = &sdev->pilot_info.enabled; | ||
989 | break; | 951 | break; |
990 | 952 | ||
991 | case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: | 953 | case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: |
992 | *property = SI4713_TX_LIMITER_RELEASE_TIME; | 954 | *property = SI4713_TX_LIMITER_RELEASE_TIME; |
993 | *table = limiter_times; | 955 | *table = limiter_times; |
994 | *size = ARRAY_SIZE(limiter_times); | 956 | *size = ARRAY_SIZE(limiter_times); |
995 | *shadow = &sdev->limiter_info.release_time; | ||
996 | break; | 957 | break; |
997 | case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: | 958 | case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: |
998 | *property = SI4713_TX_ACOMP_RELEASE_TIME; | 959 | *property = SI4713_TX_ACOMP_RELEASE_TIME; |
999 | *table = acomp_rtimes; | 960 | *table = acomp_rtimes; |
1000 | *size = ARRAY_SIZE(acomp_rtimes); | 961 | *size = ARRAY_SIZE(acomp_rtimes); |
1001 | *shadow = &sdev->acomp_info.release_time; | ||
1002 | break; | 962 | break; |
1003 | case V4L2_CID_TUNE_PREEMPHASIS: | 963 | case V4L2_CID_TUNE_PREEMPHASIS: |
1004 | *property = SI4713_TX_PREEMPHASIS; | 964 | *property = SI4713_TX_PREEMPHASIS; |
1005 | *table = preemphasis_values; | 965 | *table = preemphasis_values; |
1006 | *size = ARRAY_SIZE(preemphasis_values); | 966 | *size = ARRAY_SIZE(preemphasis_values); |
1007 | *shadow = &sdev->preemphasis; | ||
1008 | break; | ||
1009 | |||
1010 | default: | ||
1011 | rval = -EINVAL; | ||
1012 | } | ||
1013 | |||
1014 | return rval; | ||
1015 | } | ||
1016 | |||
1017 | static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc); | ||
1018 | |||
1019 | /* write string property */ | ||
1020 | static int si4713_write_econtrol_string(struct si4713_device *sdev, | ||
1021 | struct v4l2_ext_control *control) | ||
1022 | { | ||
1023 | struct v4l2_queryctrl vqc; | ||
1024 | int len; | ||
1025 | s32 rval = 0; | ||
1026 | |||
1027 | vqc.id = control->id; | ||
1028 | rval = si4713_queryctrl(&sdev->sd, &vqc); | ||
1029 | if (rval < 0) | ||
1030 | goto exit; | ||
1031 | |||
1032 | switch (control->id) { | ||
1033 | case V4L2_CID_RDS_TX_PS_NAME: { | ||
1034 | char ps_name[MAX_RDS_PS_NAME + 1]; | ||
1035 | |||
1036 | len = control->size - 1; | ||
1037 | if (len < 0 || len > MAX_RDS_PS_NAME) { | ||
1038 | rval = -ERANGE; | ||
1039 | goto exit; | ||
1040 | } | ||
1041 | rval = copy_from_user(ps_name, control->string, len); | ||
1042 | if (rval) { | ||
1043 | rval = -EFAULT; | ||
1044 | goto exit; | ||
1045 | } | ||
1046 | ps_name[len] = '\0'; | ||
1047 | |||
1048 | if (strlen(ps_name) % vqc.step) { | ||
1049 | rval = -ERANGE; | ||
1050 | goto exit; | ||
1051 | } | ||
1052 | |||
1053 | rval = si4713_set_rds_ps_name(sdev, ps_name); | ||
1054 | } | ||
1055 | break; | ||
1056 | |||
1057 | case V4L2_CID_RDS_TX_RADIO_TEXT: { | ||
1058 | char radio_text[MAX_RDS_RADIO_TEXT + 1]; | ||
1059 | |||
1060 | len = control->size - 1; | ||
1061 | if (len < 0 || len > MAX_RDS_RADIO_TEXT) { | ||
1062 | rval = -ERANGE; | ||
1063 | goto exit; | ||
1064 | } | ||
1065 | rval = copy_from_user(radio_text, control->string, len); | ||
1066 | if (rval) { | ||
1067 | rval = -EFAULT; | ||
1068 | goto exit; | ||
1069 | } | ||
1070 | radio_text[len] = '\0'; | ||
1071 | |||
1072 | if (strlen(radio_text) % vqc.step) { | ||
1073 | rval = -ERANGE; | ||
1074 | goto exit; | ||
1075 | } | ||
1076 | |||
1077 | rval = si4713_set_rds_radio_text(sdev, radio_text); | ||
1078 | } | ||
1079 | break; | 967 | break; |
1080 | 968 | ||
1081 | default: | 969 | default: |
@@ -1083,136 +971,10 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev, | |||
1083 | break; | 971 | break; |
1084 | } | 972 | } |
1085 | 973 | ||
1086 | exit: | ||
1087 | return rval; | ||
1088 | } | ||
1089 | |||
1090 | static int validate_range(struct v4l2_subdev *sd, | ||
1091 | struct v4l2_ext_control *control) | ||
1092 | { | ||
1093 | struct v4l2_queryctrl vqc; | ||
1094 | int rval; | ||
1095 | |||
1096 | vqc.id = control->id; | ||
1097 | rval = si4713_queryctrl(sd, &vqc); | ||
1098 | if (rval < 0) | ||
1099 | goto exit; | ||
1100 | |||
1101 | if (control->value < vqc.minimum || control->value > vqc.maximum) | ||
1102 | rval = -ERANGE; | ||
1103 | |||
1104 | exit: | ||
1105 | return rval; | ||
1106 | } | ||
1107 | |||
1108 | /* properties which use tx_tune_power*/ | ||
1109 | static int si4713_write_econtrol_tune(struct si4713_device *sdev, | ||
1110 | struct v4l2_ext_control *control) | ||
1111 | { | ||
1112 | s32 rval = 0; | ||
1113 | u8 power, antcap; | ||
1114 | |||
1115 | rval = validate_range(&sdev->sd, control); | ||
1116 | if (rval < 0) | ||
1117 | goto exit; | ||
1118 | |||
1119 | mutex_lock(&sdev->mutex); | ||
1120 | |||
1121 | switch (control->id) { | ||
1122 | case V4L2_CID_TUNE_POWER_LEVEL: | ||
1123 | power = control->value; | ||
1124 | antcap = sdev->antenna_capacitor; | ||
1125 | break; | ||
1126 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | ||
1127 | power = sdev->power_level; | ||
1128 | antcap = control->value; | ||
1129 | break; | ||
1130 | default: | ||
1131 | rval = -EINVAL; | ||
1132 | goto unlock; | ||
1133 | } | ||
1134 | |||
1135 | if (sdev->power_state) | ||
1136 | rval = si4713_tx_tune_power(sdev, power, antcap); | ||
1137 | |||
1138 | if (rval == 0) { | ||
1139 | sdev->power_level = power; | ||
1140 | sdev->antenna_capacitor = antcap; | ||
1141 | } | ||
1142 | |||
1143 | unlock: | ||
1144 | mutex_unlock(&sdev->mutex); | ||
1145 | exit: | ||
1146 | return rval; | ||
1147 | } | ||
1148 | |||
1149 | static int si4713_write_econtrol_integers(struct si4713_device *sdev, | ||
1150 | struct v4l2_ext_control *control) | ||
1151 | { | ||
1152 | s32 rval; | ||
1153 | u32 *shadow = NULL, val = 0; | ||
1154 | s32 bit = 0, mask = 0; | ||
1155 | u16 property = 0; | ||
1156 | int mul = 0; | ||
1157 | unsigned long *table = NULL; | ||
1158 | int size = 0; | ||
1159 | |||
1160 | rval = validate_range(&sdev->sd, control); | ||
1161 | if (rval < 0) | ||
1162 | goto exit; | ||
1163 | |||
1164 | rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, | ||
1165 | &mask, &property, &mul, &table, &size); | ||
1166 | if (rval < 0) | ||
1167 | goto exit; | ||
1168 | |||
1169 | val = control->value; | ||
1170 | if (mul) { | ||
1171 | val = control->value / mul; | ||
1172 | } else if (table) { | ||
1173 | rval = usecs_to_dev(control->value, table, size); | ||
1174 | if (rval < 0) | ||
1175 | goto exit; | ||
1176 | val = rval; | ||
1177 | rval = 0; | ||
1178 | } | ||
1179 | |||
1180 | mutex_lock(&sdev->mutex); | ||
1181 | |||
1182 | if (sdev->power_state) { | ||
1183 | if (mask) { | ||
1184 | rval = si4713_read_property(sdev, property, &val); | ||
1185 | if (rval < 0) | ||
1186 | goto unlock; | ||
1187 | val = set_bits(val, control->value, bit, mask); | ||
1188 | } | ||
1189 | |||
1190 | rval = si4713_write_property(sdev, property, val); | ||
1191 | if (rval < 0) | ||
1192 | goto unlock; | ||
1193 | if (mask) | ||
1194 | val = control->value; | ||
1195 | } | ||
1196 | |||
1197 | if (mul) { | ||
1198 | *shadow = val * mul; | ||
1199 | } else if (table) { | ||
1200 | rval = dev_to_usecs(val, table, size); | ||
1201 | if (rval < 0) | ||
1202 | goto unlock; | ||
1203 | *shadow = rval; | ||
1204 | rval = 0; | ||
1205 | } else { | ||
1206 | *shadow = val; | ||
1207 | } | ||
1208 | |||
1209 | unlock: | ||
1210 | mutex_unlock(&sdev->mutex); | ||
1211 | exit: | ||
1212 | return rval; | 974 | return rval; |
1213 | } | 975 | } |
1214 | 976 | ||
1215 | static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f); | 977 | static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f); |
1216 | static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *); | 978 | static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *); |
1217 | /* | 979 | /* |
1218 | * si4713_setup - Sets the device up with current configuration. | 980 | * si4713_setup - Sets the device up with current configuration. |
@@ -1220,111 +982,25 @@ static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulato | |||
1220 | */ | 982 | */ |
1221 | static int si4713_setup(struct si4713_device *sdev) | 983 | static int si4713_setup(struct si4713_device *sdev) |
1222 | { | 984 | { |
1223 | struct v4l2_ext_control ctrl; | ||
1224 | struct v4l2_frequency f; | 985 | struct v4l2_frequency f; |
1225 | struct v4l2_modulator vm; | 986 | struct v4l2_modulator vm; |
1226 | struct si4713_device *tmp; | 987 | int rval; |
1227 | int rval = 0; | ||
1228 | |||
1229 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | ||
1230 | if (!tmp) | ||
1231 | return -ENOMEM; | ||
1232 | |||
1233 | /* Get a local copy to avoid race */ | ||
1234 | mutex_lock(&sdev->mutex); | ||
1235 | memcpy(tmp, sdev, sizeof(*sdev)); | ||
1236 | mutex_unlock(&sdev->mutex); | ||
1237 | |||
1238 | ctrl.id = V4L2_CID_RDS_TX_PI; | ||
1239 | ctrl.value = tmp->rds_info.pi; | ||
1240 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1241 | |||
1242 | ctrl.id = V4L2_CID_AUDIO_COMPRESSION_THRESHOLD; | ||
1243 | ctrl.value = tmp->acomp_info.threshold; | ||
1244 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1245 | |||
1246 | ctrl.id = V4L2_CID_AUDIO_COMPRESSION_GAIN; | ||
1247 | ctrl.value = tmp->acomp_info.gain; | ||
1248 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1249 | |||
1250 | ctrl.id = V4L2_CID_PILOT_TONE_FREQUENCY; | ||
1251 | ctrl.value = tmp->pilot_info.frequency; | ||
1252 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1253 | |||
1254 | ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME; | ||
1255 | ctrl.value = tmp->acomp_info.attack_time; | ||
1256 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1257 | |||
1258 | ctrl.id = V4L2_CID_PILOT_TONE_DEVIATION; | ||
1259 | ctrl.value = tmp->pilot_info.deviation; | ||
1260 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1261 | |||
1262 | ctrl.id = V4L2_CID_AUDIO_LIMITER_DEVIATION; | ||
1263 | ctrl.value = tmp->limiter_info.deviation; | ||
1264 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1265 | |||
1266 | ctrl.id = V4L2_CID_RDS_TX_DEVIATION; | ||
1267 | ctrl.value = tmp->rds_info.deviation; | ||
1268 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1269 | |||
1270 | ctrl.id = V4L2_CID_RDS_TX_PTY; | ||
1271 | ctrl.value = tmp->rds_info.pty; | ||
1272 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1273 | |||
1274 | ctrl.id = V4L2_CID_AUDIO_LIMITER_ENABLED; | ||
1275 | ctrl.value = tmp->limiter_info.enabled; | ||
1276 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1277 | |||
1278 | ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ENABLED; | ||
1279 | ctrl.value = tmp->acomp_info.enabled; | ||
1280 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1281 | |||
1282 | ctrl.id = V4L2_CID_PILOT_TONE_ENABLED; | ||
1283 | ctrl.value = tmp->pilot_info.enabled; | ||
1284 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1285 | |||
1286 | ctrl.id = V4L2_CID_AUDIO_LIMITER_RELEASE_TIME; | ||
1287 | ctrl.value = tmp->limiter_info.release_time; | ||
1288 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1289 | |||
1290 | ctrl.id = V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME; | ||
1291 | ctrl.value = tmp->acomp_info.release_time; | ||
1292 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1293 | |||
1294 | ctrl.id = V4L2_CID_TUNE_PREEMPHASIS; | ||
1295 | ctrl.value = tmp->preemphasis; | ||
1296 | rval |= si4713_write_econtrol_integers(sdev, &ctrl); | ||
1297 | |||
1298 | ctrl.id = V4L2_CID_RDS_TX_PS_NAME; | ||
1299 | rval |= si4713_set_rds_ps_name(sdev, tmp->rds_info.ps_name); | ||
1300 | |||
1301 | ctrl.id = V4L2_CID_RDS_TX_RADIO_TEXT; | ||
1302 | rval |= si4713_set_rds_radio_text(sdev, tmp->rds_info.radio_text); | ||
1303 | 988 | ||
1304 | /* Device procedure needs to set frequency first */ | 989 | /* Device procedure needs to set frequency first */ |
1305 | f.frequency = tmp->frequency ? tmp->frequency : DEFAULT_FREQUENCY; | 990 | f.tuner = 0; |
991 | f.frequency = sdev->frequency ? sdev->frequency : DEFAULT_FREQUENCY; | ||
1306 | f.frequency = si4713_to_v4l2(f.frequency); | 992 | f.frequency = si4713_to_v4l2(f.frequency); |
1307 | rval |= si4713_s_frequency(&sdev->sd, &f); | 993 | rval = si4713_s_frequency(&sdev->sd, &f); |
1308 | |||
1309 | ctrl.id = V4L2_CID_TUNE_POWER_LEVEL; | ||
1310 | ctrl.value = tmp->power_level; | ||
1311 | rval |= si4713_write_econtrol_tune(sdev, &ctrl); | ||
1312 | |||
1313 | ctrl.id = V4L2_CID_TUNE_ANTENNA_CAPACITOR; | ||
1314 | ctrl.value = tmp->antenna_capacitor; | ||
1315 | rval |= si4713_write_econtrol_tune(sdev, &ctrl); | ||
1316 | 994 | ||
1317 | vm.index = 0; | 995 | vm.index = 0; |
1318 | if (tmp->stereo) | 996 | if (sdev->stereo) |
1319 | vm.txsubchans = V4L2_TUNER_SUB_STEREO; | 997 | vm.txsubchans = V4L2_TUNER_SUB_STEREO; |
1320 | else | 998 | else |
1321 | vm.txsubchans = V4L2_TUNER_SUB_MONO; | 999 | vm.txsubchans = V4L2_TUNER_SUB_MONO; |
1322 | if (tmp->rds_info.enabled) | 1000 | if (sdev->rds_enabled) |
1323 | vm.txsubchans |= V4L2_TUNER_SUB_RDS; | 1001 | vm.txsubchans |= V4L2_TUNER_SUB_RDS; |
1324 | si4713_s_modulator(&sdev->sd, &vm); | 1002 | si4713_s_modulator(&sdev->sd, &vm); |
1325 | 1003 | ||
1326 | kfree(tmp); | ||
1327 | |||
1328 | return rval; | 1004 | return rval; |
1329 | } | 1005 | } |
1330 | 1006 | ||
@@ -1338,434 +1014,126 @@ static int si4713_initialize(struct si4713_device *sdev) | |||
1338 | 1014 | ||
1339 | rval = si4713_set_power_state(sdev, POWER_ON); | 1015 | rval = si4713_set_power_state(sdev, POWER_ON); |
1340 | if (rval < 0) | 1016 | if (rval < 0) |
1341 | goto exit; | 1017 | return rval; |
1342 | 1018 | ||
1343 | rval = si4713_checkrev(sdev); | 1019 | rval = si4713_checkrev(sdev); |
1344 | if (rval < 0) | 1020 | if (rval < 0) |
1345 | goto exit; | 1021 | return rval; |
1346 | 1022 | ||
1347 | rval = si4713_set_power_state(sdev, POWER_OFF); | 1023 | rval = si4713_set_power_state(sdev, POWER_OFF); |
1348 | if (rval < 0) | 1024 | if (rval < 0) |
1349 | goto exit; | 1025 | return rval; |
1350 | |||
1351 | mutex_lock(&sdev->mutex); | ||
1352 | |||
1353 | sdev->rds_info.pi = DEFAULT_RDS_PI; | ||
1354 | sdev->rds_info.pty = DEFAULT_RDS_PTY; | ||
1355 | sdev->rds_info.deviation = DEFAULT_RDS_DEVIATION; | ||
1356 | strlcpy(sdev->rds_info.ps_name, DEFAULT_RDS_PS_NAME, MAX_RDS_PS_NAME); | ||
1357 | strlcpy(sdev->rds_info.radio_text, DEFAULT_RDS_RADIO_TEXT, | ||
1358 | MAX_RDS_RADIO_TEXT); | ||
1359 | sdev->rds_info.enabled = 1; | ||
1360 | |||
1361 | sdev->limiter_info.release_time = DEFAULT_LIMITER_RTIME; | ||
1362 | sdev->limiter_info.deviation = DEFAULT_LIMITER_DEV; | ||
1363 | sdev->limiter_info.enabled = 1; | ||
1364 | |||
1365 | sdev->pilot_info.deviation = DEFAULT_PILOT_DEVIATION; | ||
1366 | sdev->pilot_info.frequency = DEFAULT_PILOT_FREQUENCY; | ||
1367 | sdev->pilot_info.enabled = 1; | ||
1368 | 1026 | ||
1369 | sdev->acomp_info.release_time = DEFAULT_ACOMP_RTIME; | ||
1370 | sdev->acomp_info.attack_time = DEFAULT_ACOMP_ATIME; | ||
1371 | sdev->acomp_info.threshold = DEFAULT_ACOMP_THRESHOLD; | ||
1372 | sdev->acomp_info.gain = DEFAULT_ACOMP_GAIN; | ||
1373 | sdev->acomp_info.enabled = 1; | ||
1374 | 1027 | ||
1375 | sdev->frequency = DEFAULT_FREQUENCY; | 1028 | sdev->frequency = DEFAULT_FREQUENCY; |
1376 | sdev->preemphasis = DEFAULT_PREEMPHASIS; | ||
1377 | sdev->mute = DEFAULT_MUTE; | ||
1378 | sdev->power_level = DEFAULT_POWER_LEVEL; | ||
1379 | sdev->antenna_capacitor = 0; | ||
1380 | sdev->stereo = 1; | 1029 | sdev->stereo = 1; |
1381 | sdev->tune_rnl = DEFAULT_TUNE_RNL; | 1030 | sdev->tune_rnl = DEFAULT_TUNE_RNL; |
1382 | 1031 | return 0; | |
1383 | mutex_unlock(&sdev->mutex); | ||
1384 | |||
1385 | exit: | ||
1386 | return rval; | ||
1387 | } | ||
1388 | |||
1389 | /* read string property */ | ||
1390 | static int si4713_read_econtrol_string(struct si4713_device *sdev, | ||
1391 | struct v4l2_ext_control *control) | ||
1392 | { | ||
1393 | s32 rval = 0; | ||
1394 | |||
1395 | switch (control->id) { | ||
1396 | case V4L2_CID_RDS_TX_PS_NAME: | ||
1397 | if (strlen(sdev->rds_info.ps_name) + 1 > control->size) { | ||
1398 | control->size = MAX_RDS_PS_NAME + 1; | ||
1399 | rval = -ENOSPC; | ||
1400 | goto exit; | ||
1401 | } | ||
1402 | rval = copy_to_user(control->string, sdev->rds_info.ps_name, | ||
1403 | strlen(sdev->rds_info.ps_name) + 1); | ||
1404 | if (rval) | ||
1405 | rval = -EFAULT; | ||
1406 | break; | ||
1407 | |||
1408 | case V4L2_CID_RDS_TX_RADIO_TEXT: | ||
1409 | if (strlen(sdev->rds_info.radio_text) + 1 > control->size) { | ||
1410 | control->size = MAX_RDS_RADIO_TEXT + 1; | ||
1411 | rval = -ENOSPC; | ||
1412 | goto exit; | ||
1413 | } | ||
1414 | rval = copy_to_user(control->string, sdev->rds_info.radio_text, | ||
1415 | strlen(sdev->rds_info.radio_text) + 1); | ||
1416 | if (rval) | ||
1417 | rval = -EFAULT; | ||
1418 | break; | ||
1419 | |||
1420 | default: | ||
1421 | rval = -EINVAL; | ||
1422 | break; | ||
1423 | } | ||
1424 | |||
1425 | exit: | ||
1426 | return rval; | ||
1427 | } | ||
1428 | |||
1429 | /* | ||
1430 | * si4713_update_tune_status - update properties from tx_tune_status | ||
1431 | * command. Must be called with sdev->mutex held. | ||
1432 | * @sdev: si4713_device structure for the device we are communicating | ||
1433 | */ | ||
1434 | static int si4713_update_tune_status(struct si4713_device *sdev) | ||
1435 | { | ||
1436 | int rval; | ||
1437 | u16 f = 0; | ||
1438 | u8 p = 0, a = 0, n = 0; | ||
1439 | |||
1440 | rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n); | ||
1441 | |||
1442 | if (rval < 0) | ||
1443 | goto exit; | ||
1444 | |||
1445 | sdev->power_level = p; | ||
1446 | sdev->antenna_capacitor = a; | ||
1447 | sdev->tune_rnl = n; | ||
1448 | |||
1449 | exit: | ||
1450 | return rval; | ||
1451 | } | ||
1452 | |||
1453 | /* properties which use tx_tune_status */ | ||
1454 | static int si4713_read_econtrol_tune(struct si4713_device *sdev, | ||
1455 | struct v4l2_ext_control *control) | ||
1456 | { | ||
1457 | s32 rval = 0; | ||
1458 | |||
1459 | mutex_lock(&sdev->mutex); | ||
1460 | |||
1461 | if (sdev->power_state) { | ||
1462 | rval = si4713_update_tune_status(sdev); | ||
1463 | if (rval < 0) | ||
1464 | goto unlock; | ||
1465 | } | ||
1466 | |||
1467 | switch (control->id) { | ||
1468 | case V4L2_CID_TUNE_POWER_LEVEL: | ||
1469 | control->value = sdev->power_level; | ||
1470 | break; | ||
1471 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | ||
1472 | control->value = sdev->antenna_capacitor; | ||
1473 | break; | ||
1474 | default: | ||
1475 | rval = -EINVAL; | ||
1476 | } | ||
1477 | |||
1478 | unlock: | ||
1479 | mutex_unlock(&sdev->mutex); | ||
1480 | return rval; | ||
1481 | } | 1032 | } |
1482 | 1033 | ||
1483 | static int si4713_read_econtrol_integers(struct si4713_device *sdev, | 1034 | /* si4713_s_ctrl - set the value of a control */ |
1484 | struct v4l2_ext_control *control) | 1035 | static int si4713_s_ctrl(struct v4l2_ctrl *ctrl) |
1485 | { | 1036 | { |
1486 | s32 rval; | 1037 | struct si4713_device *sdev = |
1487 | u32 *shadow = NULL, val = 0; | 1038 | container_of(ctrl->handler, struct si4713_device, ctrl_handler); |
1039 | u32 val = 0; | ||
1488 | s32 bit = 0, mask = 0; | 1040 | s32 bit = 0, mask = 0; |
1489 | u16 property = 0; | 1041 | u16 property = 0; |
1490 | int mul = 0; | 1042 | int mul = 0; |
1491 | unsigned long *table = NULL; | 1043 | unsigned long *table = NULL; |
1492 | int size = 0; | 1044 | int size = 0; |
1045 | bool force = false; | ||
1046 | int c; | ||
1047 | int ret = 0; | ||
1493 | 1048 | ||
1494 | rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, | 1049 | if (ctrl->id != V4L2_CID_AUDIO_MUTE) |
1495 | &mask, &property, &mul, &table, &size); | ||
1496 | if (rval < 0) | ||
1497 | goto exit; | ||
1498 | |||
1499 | mutex_lock(&sdev->mutex); | ||
1500 | |||
1501 | if (sdev->power_state) { | ||
1502 | rval = si4713_read_property(sdev, property, &val); | ||
1503 | if (rval < 0) | ||
1504 | goto unlock; | ||
1505 | |||
1506 | /* Keep negative values for threshold */ | ||
1507 | if (control->id == V4L2_CID_AUDIO_COMPRESSION_THRESHOLD) | ||
1508 | *shadow = (s16)val; | ||
1509 | else if (mask) | ||
1510 | *shadow = get_status_bit(val, bit, mask); | ||
1511 | else if (mul) | ||
1512 | *shadow = val * mul; | ||
1513 | else | ||
1514 | *shadow = dev_to_usecs(val, table, size); | ||
1515 | } | ||
1516 | |||
1517 | control->value = *shadow; | ||
1518 | |||
1519 | unlock: | ||
1520 | mutex_unlock(&sdev->mutex); | ||
1521 | exit: | ||
1522 | return rval; | ||
1523 | } | ||
1524 | |||
1525 | /* | ||
1526 | * Video4Linux Subdev Interface | ||
1527 | */ | ||
1528 | /* si4713_s_ext_ctrls - set extended controls value */ | ||
1529 | static int si4713_s_ext_ctrls(struct v4l2_subdev *sd, | ||
1530 | struct v4l2_ext_controls *ctrls) | ||
1531 | { | ||
1532 | struct si4713_device *sdev = to_si4713_device(sd); | ||
1533 | int i; | ||
1534 | |||
1535 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) | ||
1536 | return -EINVAL; | 1050 | return -EINVAL; |
1537 | 1051 | if (ctrl->is_new) { | |
1538 | for (i = 0; i < ctrls->count; i++) { | 1052 | if (ctrl->val) { |
1539 | int err; | 1053 | ret = si4713_set_mute(sdev, ctrl->val); |
1540 | 1054 | if (!ret) | |
1541 | switch ((ctrls->controls + i)->id) { | 1055 | ret = si4713_set_power_state(sdev, POWER_DOWN); |
1542 | case V4L2_CID_RDS_TX_PS_NAME: | 1056 | return ret; |
1543 | case V4L2_CID_RDS_TX_RADIO_TEXT: | ||
1544 | err = si4713_write_econtrol_string(sdev, | ||
1545 | ctrls->controls + i); | ||
1546 | break; | ||
1547 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | ||
1548 | case V4L2_CID_TUNE_POWER_LEVEL: | ||
1549 | err = si4713_write_econtrol_tune(sdev, | ||
1550 | ctrls->controls + i); | ||
1551 | break; | ||
1552 | default: | ||
1553 | err = si4713_write_econtrol_integers(sdev, | ||
1554 | ctrls->controls + i); | ||
1555 | } | ||
1556 | |||
1557 | if (err < 0) { | ||
1558 | ctrls->error_idx = i; | ||
1559 | return err; | ||
1560 | } | 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; | ||
1561 | } | 1066 | } |
1562 | 1067 | ||
1563 | return 0; | 1068 | if (!sdev->power_state) |
1564 | } | 1069 | return 0; |
1565 | 1070 | ||
1566 | /* si4713_g_ext_ctrls - get extended controls value */ | 1071 | for (c = 1; !ret && c < ctrl->ncontrols; c++) { |
1567 | static int si4713_g_ext_ctrls(struct v4l2_subdev *sd, | 1072 | ctrl = ctrl->cluster[c]; |
1568 | struct v4l2_ext_controls *ctrls) | ||
1569 | { | ||
1570 | struct si4713_device *sdev = to_si4713_device(sd); | ||
1571 | int i; | ||
1572 | 1073 | ||
1573 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) | 1074 | if (!force && !ctrl->is_new) |
1574 | return -EINVAL; | 1075 | continue; |
1575 | 1076 | ||
1576 | for (i = 0; i < ctrls->count; i++) { | 1077 | switch (ctrl->id) { |
1577 | int err; | ||
1578 | |||
1579 | switch ((ctrls->controls + i)->id) { | ||
1580 | 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 | |||
1581 | case V4L2_CID_RDS_TX_RADIO_TEXT: | 1082 | case V4L2_CID_RDS_TX_RADIO_TEXT: |
1582 | err = si4713_read_econtrol_string(sdev, | 1083 | ret = si4713_set_rds_radio_text(sdev, ctrl->string); |
1583 | ctrls->controls + i); | ||
1584 | break; | 1084 | break; |
1085 | |||
1585 | 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 */ | ||
1586 | case V4L2_CID_TUNE_POWER_LEVEL: | 1093 | case V4L2_CID_TUNE_POWER_LEVEL: |
1587 | err = si4713_read_econtrol_tune(sdev, | 1094 | ret = si4713_tx_tune_power(sdev, |
1588 | 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 | } | ||
1589 | break; | 1101 | break; |
1590 | default: | ||
1591 | err = si4713_read_econtrol_integers(sdev, | ||
1592 | ctrls->controls + i); | ||
1593 | } | ||
1594 | |||
1595 | if (err < 0) { | ||
1596 | ctrls->error_idx = i; | ||
1597 | return err; | ||
1598 | } | ||
1599 | } | ||
1600 | |||
1601 | return 0; | ||
1602 | } | ||
1603 | |||
1604 | /* si4713_queryctrl - enumerate control items */ | ||
1605 | static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | ||
1606 | { | ||
1607 | int rval = 0; | ||
1608 | |||
1609 | switch (qc->id) { | ||
1610 | /* User class controls */ | ||
1611 | case V4L2_CID_AUDIO_MUTE: | ||
1612 | rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, DEFAULT_MUTE); | ||
1613 | break; | ||
1614 | /* FM_TX class controls */ | ||
1615 | case V4L2_CID_RDS_TX_PI: | ||
1616 | rval = v4l2_ctrl_query_fill(qc, 0, 0xFFFF, 1, DEFAULT_RDS_PI); | ||
1617 | break; | ||
1618 | case V4L2_CID_RDS_TX_PTY: | ||
1619 | rval = v4l2_ctrl_query_fill(qc, 0, 31, 1, DEFAULT_RDS_PTY); | ||
1620 | break; | ||
1621 | case V4L2_CID_RDS_TX_DEVIATION: | ||
1622 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_DEVIATION, | ||
1623 | 10, DEFAULT_RDS_DEVIATION); | ||
1624 | break; | ||
1625 | case V4L2_CID_RDS_TX_PS_NAME: | ||
1626 | /* | ||
1627 | * Report step as 8. From RDS spec, psname | ||
1628 | * should be 8. But there are receivers which scroll strings | ||
1629 | * sized as 8xN. | ||
1630 | */ | ||
1631 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_PS_NAME, 8, 0); | ||
1632 | break; | ||
1633 | case V4L2_CID_RDS_TX_RADIO_TEXT: | ||
1634 | /* | ||
1635 | * Report step as 32 (2A block). From RDS spec, | ||
1636 | * radio text should be 32 for 2A block. But there are receivers | ||
1637 | * which scroll strings sized as 32xN. Setting default to 32. | ||
1638 | */ | ||
1639 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_RADIO_TEXT, 32, 0); | ||
1640 | break; | ||
1641 | |||
1642 | case V4L2_CID_AUDIO_LIMITER_ENABLED: | ||
1643 | rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); | ||
1644 | break; | ||
1645 | case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: | ||
1646 | rval = v4l2_ctrl_query_fill(qc, 250, MAX_LIMITER_RELEASE_TIME, | ||
1647 | 50, DEFAULT_LIMITER_RTIME); | ||
1648 | break; | ||
1649 | case V4L2_CID_AUDIO_LIMITER_DEVIATION: | ||
1650 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_LIMITER_DEVIATION, | ||
1651 | 10, DEFAULT_LIMITER_DEV); | ||
1652 | break; | ||
1653 | |||
1654 | case V4L2_CID_AUDIO_COMPRESSION_ENABLED: | ||
1655 | rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); | ||
1656 | break; | ||
1657 | case V4L2_CID_AUDIO_COMPRESSION_GAIN: | ||
1658 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_GAIN, 1, | ||
1659 | DEFAULT_ACOMP_GAIN); | ||
1660 | break; | ||
1661 | case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: | ||
1662 | rval = v4l2_ctrl_query_fill(qc, MIN_ACOMP_THRESHOLD, | ||
1663 | MAX_ACOMP_THRESHOLD, 1, | ||
1664 | DEFAULT_ACOMP_THRESHOLD); | ||
1665 | break; | ||
1666 | case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: | ||
1667 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_ATTACK_TIME, | ||
1668 | 500, DEFAULT_ACOMP_ATIME); | ||
1669 | break; | ||
1670 | case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: | ||
1671 | rval = v4l2_ctrl_query_fill(qc, 100000, MAX_ACOMP_RELEASE_TIME, | ||
1672 | 100000, DEFAULT_ACOMP_RTIME); | ||
1673 | break; | ||
1674 | |||
1675 | case V4L2_CID_PILOT_TONE_ENABLED: | ||
1676 | rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); | ||
1677 | break; | ||
1678 | case V4L2_CID_PILOT_TONE_DEVIATION: | ||
1679 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_DEVIATION, | ||
1680 | 10, DEFAULT_PILOT_DEVIATION); | ||
1681 | break; | ||
1682 | case V4L2_CID_PILOT_TONE_FREQUENCY: | ||
1683 | rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_FREQUENCY, | ||
1684 | 1, DEFAULT_PILOT_FREQUENCY); | ||
1685 | break; | ||
1686 | |||
1687 | case V4L2_CID_TUNE_PREEMPHASIS: | ||
1688 | rval = v4l2_ctrl_query_fill(qc, V4L2_PREEMPHASIS_DISABLED, | ||
1689 | V4L2_PREEMPHASIS_75_uS, 1, | ||
1690 | V4L2_PREEMPHASIS_50_uS); | ||
1691 | break; | ||
1692 | case V4L2_CID_TUNE_POWER_LEVEL: | ||
1693 | rval = v4l2_ctrl_query_fill(qc, 0, 120, 1, DEFAULT_POWER_LEVEL); | ||
1694 | break; | ||
1695 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | ||
1696 | rval = v4l2_ctrl_query_fill(qc, 0, 191, 1, 0); | ||
1697 | break; | ||
1698 | default: | ||
1699 | rval = -EINVAL; | ||
1700 | break; | ||
1701 | } | ||
1702 | |||
1703 | return rval; | ||
1704 | } | ||
1705 | |||
1706 | /* si4713_g_ctrl - get the value of a control */ | ||
1707 | static int si4713_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
1708 | { | ||
1709 | struct si4713_device *sdev = to_si4713_device(sd); | ||
1710 | int rval = 0; | ||
1711 | |||
1712 | if (!sdev) | ||
1713 | return -ENODEV; | ||
1714 | |||
1715 | mutex_lock(&sdev->mutex); | ||
1716 | |||
1717 | if (sdev->power_state) { | ||
1718 | rval = si4713_read_property(sdev, SI4713_TX_LINE_INPUT_MUTE, | ||
1719 | &sdev->mute); | ||
1720 | |||
1721 | if (rval < 0) | ||
1722 | goto unlock; | ||
1723 | } | ||
1724 | |||
1725 | switch (ctrl->id) { | ||
1726 | case V4L2_CID_AUDIO_MUTE: | ||
1727 | ctrl->value = get_mute(sdev->mute); | ||
1728 | break; | ||
1729 | } | ||
1730 | |||
1731 | unlock: | ||
1732 | mutex_unlock(&sdev->mutex); | ||
1733 | return rval; | ||
1734 | } | ||
1735 | |||
1736 | /* si4713_s_ctrl - set the value of a control */ | ||
1737 | static int si4713_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
1738 | { | ||
1739 | struct si4713_device *sdev = to_si4713_device(sd); | ||
1740 | int rval = 0; | ||
1741 | |||
1742 | if (!sdev) | ||
1743 | return -ENODEV; | ||
1744 | |||
1745 | switch (ctrl->id) { | ||
1746 | case V4L2_CID_AUDIO_MUTE: | ||
1747 | if (ctrl->value) { | ||
1748 | rval = si4713_set_mute(sdev, ctrl->value); | ||
1749 | if (rval < 0) | ||
1750 | goto exit; | ||
1751 | 1102 | ||
1752 | rval = si4713_set_power_state(sdev, POWER_DOWN); | 1103 | default: |
1753 | } else { | 1104 | ret = si4713_choose_econtrol_action(sdev, ctrl->id, &bit, |
1754 | rval = si4713_set_power_state(sdev, POWER_UP); | 1105 | &mask, &property, &mul, &table, &size); |
1755 | if (rval < 0) | 1106 | if (ret < 0) |
1756 | goto exit; | 1107 | break; |
1108 | |||
1109 | val = ctrl->val; | ||
1110 | if (mul) { | ||
1111 | val = val / mul; | ||
1112 | } else if (table) { | ||
1113 | ret = usecs_to_dev(val, table, size); | ||
1114 | if (ret < 0) | ||
1115 | break; | ||
1116 | val = ret; | ||
1117 | ret = 0; | ||
1118 | } | ||
1757 | 1119 | ||
1758 | rval = si4713_setup(sdev); | 1120 | if (mask) { |
1759 | if (rval < 0) | 1121 | ret = si4713_read_property(sdev, property, &val); |
1760 | goto exit; | 1122 | if (ret < 0) |
1123 | break; | ||
1124 | val = set_bits(val, ctrl->val, bit, mask); | ||
1125 | } | ||
1761 | 1126 | ||
1762 | 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; | ||
1763 | } | 1133 | } |
1764 | break; | ||
1765 | } | 1134 | } |
1766 | 1135 | ||
1767 | exit: | 1136 | return ret; |
1768 | return rval; | ||
1769 | } | 1137 | } |
1770 | 1138 | ||
1771 | /* si4713_ioctl - deal with private ioctls (only rnl for now) */ | 1139 | /* si4713_ioctl - deal with private ioctls (only rnl for now) */ |
@@ -1779,7 +1147,6 @@ static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) | |||
1779 | if (!arg) | 1147 | if (!arg) |
1780 | return -EINVAL; | 1148 | return -EINVAL; |
1781 | 1149 | ||
1782 | mutex_lock(&sdev->mutex); | ||
1783 | switch (cmd) { | 1150 | switch (cmd) { |
1784 | case SI4713_IOC_MEASURE_RNL: | 1151 | case SI4713_IOC_MEASURE_RNL: |
1785 | frequency = v4l2_to_si4713(rnl->frequency); | 1152 | frequency = v4l2_to_si4713(rnl->frequency); |
@@ -1788,11 +1155,11 @@ static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) | |||
1788 | /* Set desired measurement frequency */ | 1155 | /* Set desired measurement frequency */ |
1789 | rval = si4713_tx_tune_measure(sdev, frequency, 0); | 1156 | rval = si4713_tx_tune_measure(sdev, frequency, 0); |
1790 | if (rval < 0) | 1157 | if (rval < 0) |
1791 | goto unlock; | 1158 | return rval; |
1792 | /* get results from tune status */ | 1159 | /* get results from tune status */ |
1793 | rval = si4713_update_tune_status(sdev); | 1160 | rval = si4713_update_tune_status(sdev); |
1794 | if (rval < 0) | 1161 | if (rval < 0) |
1795 | goto unlock; | 1162 | return rval; |
1796 | } | 1163 | } |
1797 | rnl->rnl = sdev->tune_rnl; | 1164 | rnl->rnl = sdev->tune_rnl; |
1798 | break; | 1165 | break; |
@@ -1802,35 +1169,20 @@ static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) | |||
1802 | rval = -ENOIOCTLCMD; | 1169 | rval = -ENOIOCTLCMD; |
1803 | } | 1170 | } |
1804 | 1171 | ||
1805 | unlock: | ||
1806 | mutex_unlock(&sdev->mutex); | ||
1807 | return rval; | 1172 | return rval; |
1808 | } | 1173 | } |
1809 | 1174 | ||
1810 | static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = { | ||
1811 | .queryctrl = si4713_queryctrl, | ||
1812 | .g_ext_ctrls = si4713_g_ext_ctrls, | ||
1813 | .s_ext_ctrls = si4713_s_ext_ctrls, | ||
1814 | .g_ctrl = si4713_g_ctrl, | ||
1815 | .s_ctrl = si4713_s_ctrl, | ||
1816 | .ioctl = si4713_ioctl, | ||
1817 | }; | ||
1818 | |||
1819 | /* si4713_g_modulator - get modulator attributes */ | 1175 | /* si4713_g_modulator - get modulator attributes */ |
1820 | 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) |
1821 | { | 1177 | { |
1822 | struct si4713_device *sdev = to_si4713_device(sd); | 1178 | struct si4713_device *sdev = to_si4713_device(sd); |
1823 | int rval = 0; | 1179 | int rval = 0; |
1824 | 1180 | ||
1825 | if (!sdev) { | 1181 | if (!sdev) |
1826 | rval = -ENODEV; | 1182 | return -ENODEV; |
1827 | goto exit; | ||
1828 | } | ||
1829 | 1183 | ||
1830 | if (vm->index > 0) { | 1184 | if (vm->index > 0) |
1831 | rval = -EINVAL; | 1185 | return -EINVAL; |
1832 | goto exit; | ||
1833 | } | ||
1834 | 1186 | ||
1835 | strncpy(vm->name, "FM Modulator", 32); | 1187 | strncpy(vm->name, "FM Modulator", 32); |
1836 | vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW | | 1188 | vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW | |
@@ -1840,18 +1192,15 @@ static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) | |||
1840 | vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW); | 1192 | vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW); |
1841 | vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH); | 1193 | vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH); |
1842 | 1194 | ||
1843 | mutex_lock(&sdev->mutex); | ||
1844 | |||
1845 | if (sdev->power_state) { | 1195 | if (sdev->power_state) { |
1846 | u32 comp_en = 0; | 1196 | u32 comp_en = 0; |
1847 | 1197 | ||
1848 | rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE, | 1198 | rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE, |
1849 | &comp_en); | 1199 | &comp_en); |
1850 | if (rval < 0) | 1200 | if (rval < 0) |
1851 | goto unlock; | 1201 | return rval; |
1852 | 1202 | ||
1853 | sdev->stereo = get_status_bit(comp_en, 1, 1 << 1); | 1203 | sdev->stereo = get_status_bit(comp_en, 1, 1 << 1); |
1854 | sdev->rds_info.enabled = get_status_bit(comp_en, 2, 1 << 2); | ||
1855 | } | 1204 | } |
1856 | 1205 | ||
1857 | /* Report current audio mode: mono or stereo */ | 1206 | /* Report current audio mode: mono or stereo */ |
@@ -1861,14 +1210,11 @@ static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) | |||
1861 | vm->txsubchans = V4L2_TUNER_SUB_MONO; | 1210 | vm->txsubchans = V4L2_TUNER_SUB_MONO; |
1862 | 1211 | ||
1863 | /* Report rds feature status */ | 1212 | /* Report rds feature status */ |
1864 | if (sdev->rds_info.enabled) | 1213 | if (sdev->rds_enabled) |
1865 | vm->txsubchans |= V4L2_TUNER_SUB_RDS; | 1214 | vm->txsubchans |= V4L2_TUNER_SUB_RDS; |
1866 | else | 1215 | else |
1867 | vm->txsubchans &= ~V4L2_TUNER_SUB_RDS; | 1216 | vm->txsubchans &= ~V4L2_TUNER_SUB_RDS; |
1868 | 1217 | ||
1869 | unlock: | ||
1870 | mutex_unlock(&sdev->mutex); | ||
1871 | exit: | ||
1872 | return rval; | 1218 | return rval; |
1873 | } | 1219 | } |
1874 | 1220 | ||
@@ -1896,13 +1242,11 @@ static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulato | |||
1896 | 1242 | ||
1897 | rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS); | 1243 | rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS); |
1898 | 1244 | ||
1899 | mutex_lock(&sdev->mutex); | ||
1900 | |||
1901 | if (sdev->power_state) { | 1245 | if (sdev->power_state) { |
1902 | rval = si4713_read_property(sdev, | 1246 | rval = si4713_read_property(sdev, |
1903 | SI4713_TX_COMPONENT_ENABLE, &p); | 1247 | SI4713_TX_COMPONENT_ENABLE, &p); |
1904 | if (rval < 0) | 1248 | if (rval < 0) |
1905 | goto unlock; | 1249 | return rval; |
1906 | 1250 | ||
1907 | p = set_bits(p, stereo, 1, 1 << 1); | 1251 | p = set_bits(p, stereo, 1, 1 << 1); |
1908 | p = set_bits(p, rds, 2, 1 << 2); | 1252 | p = set_bits(p, rds, 2, 1 << 2); |
@@ -1910,14 +1254,12 @@ static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulato | |||
1910 | rval = si4713_write_property(sdev, | 1254 | rval = si4713_write_property(sdev, |
1911 | SI4713_TX_COMPONENT_ENABLE, p); | 1255 | SI4713_TX_COMPONENT_ENABLE, p); |
1912 | if (rval < 0) | 1256 | if (rval < 0) |
1913 | goto unlock; | 1257 | return rval; |
1914 | } | 1258 | } |
1915 | 1259 | ||
1916 | sdev->stereo = stereo; | 1260 | sdev->stereo = stereo; |
1917 | sdev->rds_info.enabled = rds; | 1261 | sdev->rds_enabled = rds; |
1918 | 1262 | ||
1919 | unlock: | ||
1920 | mutex_unlock(&sdev->mutex); | ||
1921 | return rval; | 1263 | return rval; |
1922 | } | 1264 | } |
1923 | 1265 | ||
@@ -1927,9 +1269,8 @@ static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) | |||
1927 | struct si4713_device *sdev = to_si4713_device(sd); | 1269 | struct si4713_device *sdev = to_si4713_device(sd); |
1928 | int rval = 0; | 1270 | int rval = 0; |
1929 | 1271 | ||
1930 | f->type = V4L2_TUNER_RADIO; | 1272 | if (f->tuner) |
1931 | 1273 | return -EINVAL; | |
1932 | mutex_lock(&sdev->mutex); | ||
1933 | 1274 | ||
1934 | if (sdev->power_state) { | 1275 | if (sdev->power_state) { |
1935 | u16 freq; | 1276 | u16 freq; |
@@ -1937,46 +1278,49 @@ static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) | |||
1937 | 1278 | ||
1938 | rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n); | 1279 | rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n); |
1939 | if (rval < 0) | 1280 | if (rval < 0) |
1940 | goto unlock; | 1281 | return rval; |
1941 | 1282 | ||
1942 | sdev->frequency = freq; | 1283 | sdev->frequency = freq; |
1943 | } | 1284 | } |
1944 | 1285 | ||
1945 | f->frequency = si4713_to_v4l2(sdev->frequency); | 1286 | f->frequency = si4713_to_v4l2(sdev->frequency); |
1946 | 1287 | ||
1947 | unlock: | ||
1948 | mutex_unlock(&sdev->mutex); | ||
1949 | return rval; | 1288 | return rval; |
1950 | } | 1289 | } |
1951 | 1290 | ||
1952 | /* si4713_s_frequency - set tuner or modulator radio frequency */ | 1291 | /* si4713_s_frequency - set tuner or modulator radio frequency */ |
1953 | static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) | 1292 | static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f) |
1954 | { | 1293 | { |
1955 | struct si4713_device *sdev = to_si4713_device(sd); | 1294 | struct si4713_device *sdev = to_si4713_device(sd); |
1956 | int rval = 0; | 1295 | int rval = 0; |
1957 | u16 frequency = v4l2_to_si4713(f->frequency); | 1296 | u16 frequency = v4l2_to_si4713(f->frequency); |
1958 | 1297 | ||
1959 | /* Check frequency range */ | 1298 | if (f->tuner) |
1960 | if (frequency < FREQ_RANGE_LOW || frequency > FREQ_RANGE_HIGH) | 1299 | return -EINVAL; |
1961 | return -EDOM; | ||
1962 | 1300 | ||
1963 | mutex_lock(&sdev->mutex); | 1301 | /* Check frequency range */ |
1302 | frequency = clamp_t(u16, frequency, FREQ_RANGE_LOW, FREQ_RANGE_HIGH); | ||
1964 | 1303 | ||
1965 | if (sdev->power_state) { | 1304 | if (sdev->power_state) { |
1966 | rval = si4713_tx_tune_freq(sdev, frequency); | 1305 | rval = si4713_tx_tune_freq(sdev, frequency); |
1967 | if (rval < 0) | 1306 | if (rval < 0) |
1968 | goto unlock; | 1307 | return rval; |
1969 | frequency = rval; | 1308 | frequency = rval; |
1970 | rval = 0; | 1309 | rval = 0; |
1971 | } | 1310 | } |
1972 | sdev->frequency = frequency; | 1311 | sdev->frequency = frequency; |
1973 | f->frequency = si4713_to_v4l2(frequency); | ||
1974 | 1312 | ||
1975 | unlock: | ||
1976 | mutex_unlock(&sdev->mutex); | ||
1977 | return rval; | 1313 | return rval; |
1978 | } | 1314 | } |
1979 | 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 | |||
1980 | static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = { | 1324 | static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = { |
1981 | .g_frequency = si4713_g_frequency, | 1325 | .g_frequency = si4713_g_frequency, |
1982 | .s_frequency = si4713_s_frequency, | 1326 | .s_frequency = si4713_s_frequency, |
@@ -1998,6 +1342,7 @@ static int si4713_probe(struct i2c_client *client, | |||
1998 | { | 1342 | { |
1999 | struct si4713_device *sdev; | 1343 | struct si4713_device *sdev; |
2000 | 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; | ||
2001 | int rval, i; | 1346 | int rval, i; |
2002 | 1347 | ||
2003 | sdev = kzalloc(sizeof *sdev, GFP_KERNEL); | 1348 | sdev = kzalloc(sizeof *sdev, GFP_KERNEL); |
@@ -2031,9 +1376,84 @@ static int si4713_probe(struct i2c_client *client, | |||
2031 | 1376 | ||
2032 | v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops); | 1377 | v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops); |
2033 | 1378 | ||
2034 | mutex_init(&sdev->mutex); | ||
2035 | init_completion(&sdev->work); | 1379 | init_completion(&sdev->work); |
2036 | 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 | |||
2037 | if (client->irq) { | 1457 | if (client->irq) { |
2038 | rval = request_irq(client->irq, | 1458 | rval = request_irq(client->irq, |
2039 | si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, | 1459 | si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, |
@@ -2058,6 +1478,8 @@ static int si4713_probe(struct i2c_client *client, | |||
2058 | free_irq: | 1478 | free_irq: |
2059 | if (client->irq) | 1479 | if (client->irq) |
2060 | free_irq(client->irq, sdev); | 1480 | free_irq(client->irq, sdev); |
1481 | free_ctrls: | ||
1482 | v4l2_ctrl_handler_free(hdl); | ||
2061 | put_reg: | 1483 | put_reg: |
2062 | regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); | 1484 | regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); |
2063 | free_gpio: | 1485 | free_gpio: |
@@ -2082,6 +1504,7 @@ static int si4713_remove(struct i2c_client *client) | |||
2082 | free_irq(client->irq, sdev); | 1504 | free_irq(client->irq, sdev); |
2083 | 1505 | ||
2084 | v4l2_device_unregister_subdev(sd); | 1506 | v4l2_device_unregister_subdev(sd); |
1507 | v4l2_ctrl_handler_free(sd->ctrl_handler); | ||
2085 | regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); | 1508 | regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); |
2086 | if (gpio_is_valid(sdev->gpio_reset)) | 1509 | if (gpio_is_valid(sdev->gpio_reset)) |
2087 | gpio_free(sdev->gpio_reset); | 1510 | gpio_free(sdev->gpio_reset); |