diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-02-04 08:42:09 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-21 19:32:01 -0400 |
commit | cbde689823776d187ba1b307a171625dbc02dd4f (patch) | |
tree | 6bb5aa1245d405fd42b81344738971356ee38d93 | |
parent | e2d25a2474a8c0178bac4919729ab092783bd916 (diff) |
[media] tuner-core: Better implement standby mode
In the past, T_STANDBY were used on devices with a separate radio tuner to
mark a tuner that were disabled. With the time, it got newer meanings.
Also, due to a bug at the logic, the driver might incorrectly return
T_STANDBY to userspace.
So, instead of keeping the abuse, just use a boolean for storing
such information.
We can't remove T_STANDBY yet, as this is used on two other drivers. A
latter patch will address its usage outside tuner-core.
Thanks-to: Devin Heitmueller <dheitmueller@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/tuner-core.c | 189 | ||||
-rw-r--r-- | include/media/tuner.h | 1 |
2 files changed, 95 insertions, 95 deletions
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 7cdfe3af6e74..e6855a46f433 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -115,9 +115,11 @@ struct tuner { | |||
115 | unsigned int radio_freq; | 115 | unsigned int radio_freq; |
116 | unsigned int audmode; | 116 | unsigned int audmode; |
117 | 117 | ||
118 | unsigned int mode; | 118 | enum v4l2_tuner_type mode; |
119 | unsigned int mode_mask; /* Combination of allowable modes */ | 119 | unsigned int mode_mask; /* Combination of allowable modes */ |
120 | 120 | ||
121 | bool standby; /* Standby mode */ | ||
122 | |||
121 | unsigned int type; /* chip type id */ | 123 | unsigned int type; /* chip type id */ |
122 | unsigned int config; | 124 | unsigned int config; |
123 | const char *name; | 125 | const char *name; |
@@ -262,12 +264,6 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
262 | t->fe.callback = tuner_callback; | 264 | t->fe.callback = tuner_callback; |
263 | } | 265 | } |
264 | 266 | ||
265 | if (t->mode == T_UNINITIALIZED) { | ||
266 | tuner_dbg ("tuner 0x%02x: called during i2c_client register by adapter's attach_inform\n", c->addr); | ||
267 | |||
268 | return; | ||
269 | } | ||
270 | |||
271 | /* discard private data, in case set_type() was previously called */ | 267 | /* discard private data, in case set_type() was previously called */ |
272 | tuner_detach(&t->fe); | 268 | tuner_detach(&t->fe); |
273 | t->fe.analog_demod_priv = NULL; | 269 | t->fe.analog_demod_priv = NULL; |
@@ -387,8 +383,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
387 | 383 | ||
388 | tuner_dbg("type set to %s\n", t->name); | 384 | tuner_dbg("type set to %s\n", t->name); |
389 | 385 | ||
390 | if (t->mode_mask == T_UNINITIALIZED) | 386 | t->mode_mask = new_mode_mask; |
391 | t->mode_mask = new_mode_mask; | ||
392 | 387 | ||
393 | /* Some tuners require more initialization setup before use, | 388 | /* Some tuners require more initialization setup before use, |
394 | such as firmware download or device calibration. | 389 | such as firmware download or device calibration. |
@@ -411,7 +406,6 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
411 | attach_failed: | 406 | attach_failed: |
412 | tuner_dbg("Tuner attach for type = %d failed.\n", t->type); | 407 | tuner_dbg("Tuner attach for type = %d failed.\n", t->type); |
413 | t->type = TUNER_ABSENT; | 408 | t->type = TUNER_ABSENT; |
414 | t->mode_mask = T_UNINITIALIZED; | ||
415 | 409 | ||
416 | return; | 410 | return; |
417 | } | 411 | } |
@@ -429,10 +423,10 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup) | |||
429 | struct tuner *t = to_tuner(i2c_get_clientdata(c)); | 423 | struct tuner *t = to_tuner(i2c_get_clientdata(c)); |
430 | 424 | ||
431 | if ( (t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) && | 425 | if ( (t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) && |
432 | (t->mode_mask & tun_setup->mode_mask))) || | 426 | (t->mode_mask & tun_setup->mode_mask))) || |
433 | (tun_setup->addr == c->addr)) { | 427 | (tun_setup->addr == c->addr)) { |
434 | set_type(c, tun_setup->type, tun_setup->mode_mask, | 428 | set_type(c, tun_setup->type, tun_setup->mode_mask, |
435 | tun_setup->config, tun_setup->tuner_callback); | 429 | tun_setup->config, tun_setup->tuner_callback); |
436 | } else | 430 | } else |
437 | tuner_dbg("set addr discarded for type %i, mask %x. " | 431 | tuner_dbg("set addr discarded for type %i, mask %x. " |
438 | "Asked to change tuner at addr 0x%02x, with mask %x\n", | 432 | "Asked to change tuner at addr 0x%02x, with mask %x\n", |
@@ -491,7 +485,8 @@ static void tuner_lookup(struct i2c_adapter *adap, | |||
491 | strcmp(pos->i2c->driver->driver.name, "tuner")) | 485 | strcmp(pos->i2c->driver->driver.name, "tuner")) |
492 | continue; | 486 | continue; |
493 | 487 | ||
494 | mode_mask = pos->mode_mask & ~T_STANDBY; | 488 | mode_mask = pos->mode_mask; |
489 | pos->standby = 1; | ||
495 | if (*radio == NULL && mode_mask == T_RADIO) | 490 | if (*radio == NULL && mode_mask == T_RADIO) |
496 | *radio = pos; | 491 | *radio = pos; |
497 | /* Note: currently TDA9887 is the only demod-only | 492 | /* Note: currently TDA9887 is the only demod-only |
@@ -521,7 +516,9 @@ static int tuner_probe(struct i2c_client *client, | |||
521 | t->name = "(tuner unset)"; | 516 | t->name = "(tuner unset)"; |
522 | t->type = UNSET; | 517 | t->type = UNSET; |
523 | t->audmode = V4L2_TUNER_MODE_STEREO; | 518 | t->audmode = V4L2_TUNER_MODE_STEREO; |
524 | t->mode_mask = T_UNINITIALIZED; | 519 | t->standby = 1; |
520 | t->radio_freq = 87.5 * 16000; /* Initial freq range */ | ||
521 | t->tv_freq = 400 * 16; /* Sets freq to VHF High - needed for some PLL's to properly start */ | ||
525 | 522 | ||
526 | if (show_i2c) { | 523 | if (show_i2c) { |
527 | unsigned char buffer[16]; | 524 | unsigned char buffer[16]; |
@@ -544,9 +541,6 @@ static int tuner_probe(struct i2c_client *client, | |||
544 | t->i2c->addr) >= 0) { | 541 | t->i2c->addr) >= 0) { |
545 | t->type = TUNER_TEA5761; | 542 | t->type = TUNER_TEA5761; |
546 | t->mode_mask = T_RADIO; | 543 | t->mode_mask = T_RADIO; |
547 | t->mode = T_STANDBY; | ||
548 | /* Sets freq to FM range */ | ||
549 | t->radio_freq = 87.5 * 16000; | ||
550 | tuner_lookup(t->i2c->adapter, &radio, &tv); | 544 | tuner_lookup(t->i2c->adapter, &radio, &tv); |
551 | if (tv) | 545 | if (tv) |
552 | tv->mode_mask &= ~T_RADIO; | 546 | tv->mode_mask &= ~T_RADIO; |
@@ -569,7 +563,6 @@ static int tuner_probe(struct i2c_client *client, | |||
569 | t->type = TUNER_TDA9887; | 563 | t->type = TUNER_TDA9887; |
570 | t->mode_mask = T_RADIO | T_ANALOG_TV | | 564 | t->mode_mask = T_RADIO | T_ANALOG_TV | |
571 | T_DIGITAL_TV; | 565 | T_DIGITAL_TV; |
572 | t->mode = T_STANDBY; | ||
573 | goto register_client; | 566 | goto register_client; |
574 | } | 567 | } |
575 | break; | 568 | break; |
@@ -579,9 +572,7 @@ static int tuner_probe(struct i2c_client *client, | |||
579 | >= 0) { | 572 | >= 0) { |
580 | t->type = TUNER_TEA5767; | 573 | t->type = TUNER_TEA5767; |
581 | t->mode_mask = T_RADIO; | 574 | t->mode_mask = T_RADIO; |
582 | t->mode = T_STANDBY; | ||
583 | /* Sets freq to FM range */ | 575 | /* Sets freq to FM range */ |
584 | t->radio_freq = 87.5 * 16000; | ||
585 | tuner_lookup(t->i2c->adapter, &radio, &tv); | 576 | tuner_lookup(t->i2c->adapter, &radio, &tv); |
586 | if (tv) | 577 | if (tv) |
587 | tv->mode_mask &= ~T_RADIO; | 578 | tv->mode_mask &= ~T_RADIO; |
@@ -605,15 +596,10 @@ static int tuner_probe(struct i2c_client *client, | |||
605 | if (radio == NULL) | 596 | if (radio == NULL) |
606 | t->mode_mask |= T_RADIO; | 597 | t->mode_mask |= T_RADIO; |
607 | tuner_dbg("Setting mode_mask to 0x%02x\n", t->mode_mask); | 598 | tuner_dbg("Setting mode_mask to 0x%02x\n", t->mode_mask); |
608 | t->tv_freq = 400 * 16; /* Sets freq to VHF High */ | ||
609 | t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */ | ||
610 | } | 599 | } |
611 | 600 | ||
612 | /* Should be just before return */ | 601 | /* Should be just before return */ |
613 | register_client: | 602 | register_client: |
614 | tuner_info("chip found @ 0x%x (%s)\n", client->addr << 1, | ||
615 | client->adapter->name); | ||
616 | |||
617 | /* Sets a default mode */ | 603 | /* Sets a default mode */ |
618 | if (t->mode_mask & T_ANALOG_TV) { | 604 | if (t->mode_mask & T_ANALOG_TV) { |
619 | t->mode = V4L2_TUNER_ANALOG_TV; | 605 | t->mode = V4L2_TUNER_ANALOG_TV; |
@@ -624,6 +610,12 @@ register_client: | |||
624 | } | 610 | } |
625 | set_type(client, t->type, t->mode_mask, t->config, t->fe.callback); | 611 | set_type(client, t->type, t->mode_mask, t->config, t->fe.callback); |
626 | list_add_tail(&t->list, &tuner_list); | 612 | list_add_tail(&t->list, &tuner_list); |
613 | |||
614 | tuner_info("Tuner %d found with type(s)%s%s%s.\n", | ||
615 | t->type, | ||
616 | t->mode_mask & T_RADIO ? " radio" : "", | ||
617 | t->mode_mask & T_ANALOG_TV ? " TV" : "", | ||
618 | t->mode_mask & T_ANALOG_TV ? " DTV" : ""); | ||
627 | return 0; | 619 | return 0; |
628 | } | 620 | } |
629 | 621 | ||
@@ -679,6 +671,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
679 | tuner_dbg("tv freq set to %d.%02d\n", | 671 | tuner_dbg("tv freq set to %d.%02d\n", |
680 | freq / 16, freq % 16 * 100 / 16); | 672 | freq / 16, freq % 16 * 100 / 16); |
681 | t->tv_freq = freq; | 673 | t->tv_freq = freq; |
674 | t->standby = false; | ||
682 | 675 | ||
683 | analog_ops->set_params(&t->fe, ¶ms); | 676 | analog_ops->set_params(&t->fe, ¶ms); |
684 | } | 677 | } |
@@ -837,13 +830,14 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
837 | tuner_dbg("radio freq set to %d.%02d\n", | 830 | tuner_dbg("radio freq set to %d.%02d\n", |
838 | freq / 16000, freq % 16000 * 100 / 16000); | 831 | freq / 16000, freq % 16000 * 100 / 16000); |
839 | t->radio_freq = freq; | 832 | t->radio_freq = freq; |
833 | t->standby = false; | ||
840 | 834 | ||
841 | analog_ops->set_params(&t->fe, ¶ms); | 835 | analog_ops->set_params(&t->fe, ¶ms); |
842 | } | 836 | } |
843 | 837 | ||
844 | /** | 838 | /** |
845 | * check_mode - Verify if tuner supports the requested mode | 839 | * check_mode - Verify if tuner supports the requested mode |
846 | * @t - a pointer to the module's internal struct_tuner | 840 | * @t: a pointer to the module's internal struct_tuner |
847 | * | 841 | * |
848 | * This function checks if the tuner is capable of tuning analog TV, | 842 | * This function checks if the tuner is capable of tuning analog TV, |
849 | * digital TV or radio, depending on what the caller wants. If the | 843 | * digital TV or radio, depending on what the caller wants. If the |
@@ -852,51 +846,51 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) | |||
852 | * This function is needed for boards that have a separate tuner for | 846 | * This function is needed for boards that have a separate tuner for |
853 | * radio (like devices with tea5767). | 847 | * radio (like devices with tea5767). |
854 | */ | 848 | */ |
855 | static inline int check_mode(struct tuner *t) | 849 | static inline int check_mode(struct tuner *t, enum v4l2_tuner_type mode) |
856 | { | 850 | { |
857 | if ((1 << t->mode & t->mode_mask) == 0) { | 851 | if ((1 << mode & t->mode_mask) == 0) { |
858 | return -EINVAL; | 852 | return -EINVAL; |
859 | } | 853 | } |
860 | return 0; | 854 | return 0; |
861 | } | 855 | } |
862 | 856 | ||
863 | /** | 857 | /** |
864 | * set_mode - Switch tuner to other mode. | 858 | * set_mode_freq - Switch tuner to other mode. |
865 | * @client - struct i2c_client pointer | 859 | * @client: struct i2c_client pointer |
866 | * @t - a pointer to the module's internal struct_tuner | 860 | * @t: a pointer to the module's internal struct_tuner |
867 | * @mode - enum v4l2_type + T_STANDBY mode | 861 | * @mode: enum v4l2_type (radio or TV) |
868 | * @cmd - string for the command to be executed (for debug messages) | 862 | * @freq: frequency to set (0 means to use the previous one) |
869 | * | 863 | * |
870 | * If tuner doesn't support the needed mode (radio or TV), prints a | 864 | * If tuner doesn't support the needed mode (radio or TV), prints a |
871 | * debug message and returns -EINVAL, changing internal state to T_STANDBY. | 865 | * debug message and returns -EINVAL, changing internal state to T_STANDBY. |
872 | * Otherwise, changes the state and sets frequency to the last value, if | 866 | * Otherwise, changes the state and sets frequency to the last value, if |
873 | * the tuner can sleep or if it supports both Radio and TV. | 867 | * the tuner can sleep or if it supports both Radio and TV. |
874 | */ | 868 | */ |
875 | static inline int set_mode(struct i2c_client *client, struct tuner *t, | 869 | static int set_mode_freq(struct i2c_client *client, struct tuner *t, |
876 | int mode, char *cmd) | 870 | enum v4l2_tuner_type mode, unsigned int freq) |
877 | { | 871 | { |
878 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; | 872 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; |
879 | 873 | ||
880 | if (mode == t->mode) | 874 | if (mode != t->mode) { |
881 | return 0; | 875 | if (check_mode(t, mode) == -EINVAL) { |
882 | 876 | tuner_dbg("Tuner doesn't support mode %d. " | |
883 | t->mode = mode; | 877 | "Putting tuner to sleep\n", mode); |
884 | 878 | t->standby = true; | |
885 | if (check_mode(t) == -EINVAL) { | 879 | if (analog_ops->standby) |
886 | tuner_dbg("Tuner doesn't support this mode. " | 880 | analog_ops->standby(&t->fe); |
887 | "Putting tuner to sleep\n"); | 881 | return -EINVAL; |
888 | t->mode = T_STANDBY; | 882 | } |
889 | if (analog_ops->standby) | 883 | t->mode = mode; |
890 | analog_ops->standby(&t->fe); | 884 | tuner_dbg("Changing to mode %d\n", mode); |
891 | return -EINVAL; | ||
892 | } | 885 | } |
893 | |||
894 | if (t->mode == V4L2_TUNER_RADIO) { | 886 | if (t->mode == V4L2_TUNER_RADIO) { |
895 | if (t->radio_freq) | 887 | if (freq) |
896 | set_radio_freq(client, t->radio_freq); | 888 | t->radio_freq = freq; |
889 | set_radio_freq(client, t->radio_freq); | ||
897 | } else { | 890 | } else { |
898 | if (t->tv_freq) | 891 | if (freq) |
899 | set_tv_freq(client, t->tv_freq); | 892 | t->tv_freq = freq; |
893 | set_tv_freq(client, t->tv_freq); | ||
900 | } | 894 | } |
901 | 895 | ||
902 | return 0; | 896 | return 0; |
@@ -923,6 +917,13 @@ static void set_freq(struct i2c_client *c, unsigned long freq) | |||
923 | } | 917 | } |
924 | } | 918 | } |
925 | 919 | ||
920 | /** | ||
921 | * tuner_status - Dumps the current tuner status at dmesg | ||
922 | * @fe: pointer to struct dvb_frontend | ||
923 | * | ||
924 | * This callback is used only for driver debug purposes, answering to | ||
925 | * VIDIOC_LOG_STATUS. No changes should happen on this call. | ||
926 | */ | ||
926 | static void tuner_status(struct dvb_frontend *fe) | 927 | static void tuner_status(struct dvb_frontend *fe) |
927 | { | 928 | { |
928 | struct tuner *t = fe->analog_demod_priv; | 929 | struct tuner *t = fe->analog_demod_priv; |
@@ -932,10 +933,16 @@ static void tuner_status(struct dvb_frontend *fe) | |||
932 | const char *p; | 933 | const char *p; |
933 | 934 | ||
934 | switch (t->mode) { | 935 | switch (t->mode) { |
935 | case V4L2_TUNER_RADIO: p = "radio"; break; | 936 | case V4L2_TUNER_RADIO: |
936 | case V4L2_TUNER_ANALOG_TV: p = "analog TV"; break; | 937 | p = "radio"; |
937 | case V4L2_TUNER_DIGITAL_TV: p = "digital TV"; break; | 938 | break; |
938 | default: p = "undefined"; break; | 939 | case V4L2_TUNER_DIGITAL_TV: |
940 | p = "digital TV"; | ||
941 | break; | ||
942 | case V4L2_TUNER_ANALOG_TV: | ||
943 | default: | ||
944 | p = "analog TV"; | ||
945 | break; | ||
939 | } | 946 | } |
940 | if (t->mode == V4L2_TUNER_RADIO) { | 947 | if (t->mode == V4L2_TUNER_RADIO) { |
941 | freq = t->radio_freq / 16000; | 948 | freq = t->radio_freq / 16000; |
@@ -944,7 +951,8 @@ static void tuner_status(struct dvb_frontend *fe) | |||
944 | freq = t->tv_freq / 16; | 951 | freq = t->tv_freq / 16; |
945 | freq_fraction = (t->tv_freq % 16) * 100 / 16; | 952 | freq_fraction = (t->tv_freq % 16) * 100 / 16; |
946 | } | 953 | } |
947 | tuner_info("Tuner mode: %s\n", p); | 954 | tuner_info("Tuner mode: %s%s\n", p, |
955 | t->standby ? " on standby mode" : ""); | ||
948 | tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction); | 956 | tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction); |
949 | tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std); | 957 | tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std); |
950 | if (t->mode != V4L2_TUNER_RADIO) | 958 | if (t->mode != V4L2_TUNER_RADIO) |
@@ -963,19 +971,22 @@ static void tuner_status(struct dvb_frontend *fe) | |||
963 | analog_ops->has_signal(fe)); | 971 | analog_ops->has_signal(fe)); |
964 | } | 972 | } |
965 | 973 | ||
974 | /** | ||
975 | * tuner_s_power - controls the power state of the tuner | ||
976 | * @sd: pointer to struct v4l2_subdev | ||
977 | * @on: a zero value puts the tuner to sleep | ||
978 | */ | ||
966 | static int tuner_s_power(struct v4l2_subdev *sd, int on) | 979 | static int tuner_s_power(struct v4l2_subdev *sd, int on) |
967 | { | 980 | { |
968 | struct tuner *t = to_tuner(sd); | 981 | struct tuner *t = to_tuner(sd); |
969 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; | 982 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; |
970 | 983 | ||
984 | /* FIXME: Why this function don't wake the tuner if on != 0 ? */ | ||
971 | if (on) | 985 | if (on) |
972 | return 0; | 986 | return 0; |
973 | 987 | ||
974 | tuner_dbg("Putting tuner to sleep\n"); | 988 | tuner_dbg("Putting tuner to sleep\n"); |
975 | 989 | t->standby = true; | |
976 | if (check_mode(t) == -EINVAL) | ||
977 | return 0; | ||
978 | t->mode = T_STANDBY; | ||
979 | if (analog_ops->standby) | 990 | if (analog_ops->standby) |
980 | analog_ops->standby(&t->fe); | 991 | analog_ops->standby(&t->fe); |
981 | return 0; | 992 | return 0; |
@@ -983,13 +994,12 @@ static int tuner_s_power(struct v4l2_subdev *sd, int on) | |||
983 | 994 | ||
984 | /* ---------------------------------------------------------------------- */ | 995 | /* ---------------------------------------------------------------------- */ |
985 | 996 | ||
986 | |||
987 | static int tuner_s_radio(struct v4l2_subdev *sd) | 997 | static int tuner_s_radio(struct v4l2_subdev *sd) |
988 | { | 998 | { |
989 | struct tuner *t = to_tuner(sd); | 999 | struct tuner *t = to_tuner(sd); |
990 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1000 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
991 | 1001 | ||
992 | if (set_mode(client, t, V4L2_TUNER_RADIO, "s_radio") == -EINVAL) | 1002 | if (set_mode_freq(client, t, V4L2_TUNER_RADIO, 0) == -EINVAL) |
993 | return 0; | 1003 | return 0; |
994 | return 0; | 1004 | return 0; |
995 | } | 1005 | } |
@@ -1002,13 +1012,12 @@ static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
1002 | struct tuner *t = to_tuner(sd); | 1012 | struct tuner *t = to_tuner(sd); |
1003 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1013 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1004 | 1014 | ||
1005 | if (set_mode(client, t, V4L2_TUNER_ANALOG_TV, "s_std") == -EINVAL) | 1015 | if (set_mode_freq(client, t, V4L2_TUNER_ANALOG_TV, 0) == -EINVAL) |
1006 | return 0; | 1016 | return 0; |
1007 | 1017 | ||
1008 | t->std = std; | 1018 | t->std = std; |
1009 | tuner_fixup_std(t); | 1019 | tuner_fixup_std(t); |
1010 | if (t->tv_freq) | 1020 | |
1011 | set_freq(client, t->tv_freq); | ||
1012 | return 0; | 1021 | return 0; |
1013 | } | 1022 | } |
1014 | 1023 | ||
@@ -1017,9 +1026,8 @@ static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) | |||
1017 | struct tuner *t = to_tuner(sd); | 1026 | struct tuner *t = to_tuner(sd); |
1018 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1027 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1019 | 1028 | ||
1020 | if (set_mode(client, t, f->type, "s_frequency") == -EINVAL) | 1029 | if (set_mode_freq(client, t, f->type, f->frequency) == -EINVAL) |
1021 | return 0; | 1030 | return 0; |
1022 | set_freq(client, f->frequency); | ||
1023 | 1031 | ||
1024 | return 0; | 1032 | return 0; |
1025 | } | 1033 | } |
@@ -1029,20 +1037,20 @@ static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) | |||
1029 | struct tuner *t = to_tuner(sd); | 1037 | struct tuner *t = to_tuner(sd); |
1030 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | 1038 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; |
1031 | 1039 | ||
1032 | if (check_mode(t) == -EINVAL) | 1040 | if (check_mode(t, f->type) == -EINVAL) |
1033 | return 0; | 1041 | return 0; |
1034 | f->type = t->mode; | 1042 | f->type = t->mode; |
1035 | if (fe_tuner_ops->get_frequency) { | 1043 | if (fe_tuner_ops->get_frequency && !t->standby) { |
1036 | u32 abs_freq; | 1044 | u32 abs_freq; |
1037 | 1045 | ||
1038 | fe_tuner_ops->get_frequency(&t->fe, &abs_freq); | 1046 | fe_tuner_ops->get_frequency(&t->fe, &abs_freq); |
1039 | f->frequency = (V4L2_TUNER_RADIO == t->mode) ? | 1047 | f->frequency = (V4L2_TUNER_RADIO == t->mode) ? |
1040 | DIV_ROUND_CLOSEST(abs_freq * 2, 125) : | 1048 | DIV_ROUND_CLOSEST(abs_freq * 2, 125) : |
1041 | DIV_ROUND_CLOSEST(abs_freq, 62500); | 1049 | DIV_ROUND_CLOSEST(abs_freq, 62500); |
1042 | return 0; | 1050 | } else { |
1051 | f->frequency = (V4L2_TUNER_RADIO == t->mode) ? | ||
1052 | t->radio_freq : t->tv_freq; | ||
1043 | } | 1053 | } |
1044 | f->frequency = (V4L2_TUNER_RADIO == t->mode) ? | ||
1045 | t->radio_freq : t->tv_freq; | ||
1046 | return 0; | 1054 | return 0; |
1047 | } | 1055 | } |
1048 | 1056 | ||
@@ -1052,9 +1060,8 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) | |||
1052 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; | 1060 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; |
1053 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | 1061 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; |
1054 | 1062 | ||
1055 | if (check_mode(t) == -EINVAL) | 1063 | if (check_mode(t, vt->type) == -EINVAL) |
1056 | return 0; | 1064 | return 0; |
1057 | |||
1058 | vt->type = t->mode; | 1065 | vt->type = t->mode; |
1059 | if (analog_ops->get_afc) | 1066 | if (analog_ops->get_afc) |
1060 | vt->afc = analog_ops->get_afc(&t->fe); | 1067 | vt->afc = analog_ops->get_afc(&t->fe); |
@@ -1067,8 +1074,7 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) | |||
1067 | } | 1074 | } |
1068 | 1075 | ||
1069 | /* radio mode */ | 1076 | /* radio mode */ |
1070 | vt->rxsubchans = | 1077 | vt->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; |
1071 | V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | ||
1072 | if (fe_tuner_ops->get_status) { | 1078 | if (fe_tuner_ops->get_status) { |
1073 | u32 tuner_status; | 1079 | u32 tuner_status; |
1074 | 1080 | ||
@@ -1080,11 +1086,11 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) | |||
1080 | } | 1086 | } |
1081 | if (analog_ops->has_signal) | 1087 | if (analog_ops->has_signal) |
1082 | vt->signal = analog_ops->has_signal(&t->fe); | 1088 | vt->signal = analog_ops->has_signal(&t->fe); |
1083 | vt->capability |= | 1089 | vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; |
1084 | V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; | ||
1085 | vt->audmode = t->audmode; | 1090 | vt->audmode = t->audmode; |
1086 | vt->rangelow = radio_range[0] * 16000; | 1091 | vt->rangelow = radio_range[0] * 16000; |
1087 | vt->rangehigh = radio_range[1] * 16000; | 1092 | vt->rangehigh = radio_range[1] * 16000; |
1093 | |||
1088 | return 0; | 1094 | return 0; |
1089 | } | 1095 | } |
1090 | 1096 | ||
@@ -1093,14 +1099,12 @@ static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) | |||
1093 | struct tuner *t = to_tuner(sd); | 1099 | struct tuner *t = to_tuner(sd); |
1094 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1100 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1095 | 1101 | ||
1096 | if (check_mode(t) == -EINVAL) | 1102 | if (set_mode_freq(client, t, vt->type, 0) == -EINVAL) |
1097 | return 0; | 1103 | return 0; |
1098 | 1104 | ||
1099 | /* do nothing unless we're a radio tuner */ | 1105 | if (t->mode == V4L2_TUNER_RADIO) |
1100 | if (t->mode != V4L2_TUNER_RADIO) | 1106 | t->audmode = vt->audmode; |
1101 | return 0; | 1107 | |
1102 | t->audmode = vt->audmode; | ||
1103 | set_radio_freq(client, t->radio_freq); | ||
1104 | return 0; | 1108 | return 0; |
1105 | } | 1109 | } |
1106 | 1110 | ||
@@ -1128,13 +1132,10 @@ static int tuner_resume(struct i2c_client *c) | |||
1128 | struct tuner *t = to_tuner(i2c_get_clientdata(c)); | 1132 | struct tuner *t = to_tuner(i2c_get_clientdata(c)); |
1129 | 1133 | ||
1130 | tuner_dbg("resume\n"); | 1134 | tuner_dbg("resume\n"); |
1131 | if (V4L2_TUNER_RADIO == t->mode) { | 1135 | if (V4L2_TUNER_RADIO == t->mode) |
1132 | if (t->radio_freq) | 1136 | set_freq(c, t->radio_freq); |
1133 | set_freq(c, t->radio_freq); | 1137 | else |
1134 | } else { | 1138 | set_freq(c, t->tv_freq); |
1135 | if (t->tv_freq) | ||
1136 | set_freq(c, t->tv_freq); | ||
1137 | } | ||
1138 | return 0; | 1139 | return 0; |
1139 | } | 1140 | } |
1140 | 1141 | ||
diff --git a/include/media/tuner.h b/include/media/tuner.h index 5eec5292d01e..1d596427d124 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h | |||
@@ -160,7 +160,6 @@ | |||
160 | #ifdef __KERNEL__ | 160 | #ifdef __KERNEL__ |
161 | 161 | ||
162 | enum tuner_mode { | 162 | enum tuner_mode { |
163 | T_UNINITIALIZED = 0, | ||
164 | T_RADIO = 1 << V4L2_TUNER_RADIO, | 163 | T_RADIO = 1 << V4L2_TUNER_RADIO, |
165 | T_ANALOG_TV = 1 << V4L2_TUNER_ANALOG_TV, | 164 | T_ANALOG_TV = 1 << V4L2_TUNER_ANALOG_TV, |
166 | T_DIGITAL_TV = 1 << V4L2_TUNER_DIGITAL_TV, | 165 | T_DIGITAL_TV = 1 << V4L2_TUNER_DIGITAL_TV, |