diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2008-11-29 10:55:19 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-30 06:38:40 -0500 |
commit | 9415f4b2166e6d9b3095fef47f4aa7dac76ac037 (patch) | |
tree | 240fa0091c137bff3c42fb5a85f5e69be58223ca /drivers/media/video/saa7115.c | |
parent | 76efd62f1546c6fab2116d3ba832403387bd3d4a (diff) |
V4L/DVB (9826): saa7115: convert to v4l2_subdev.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/saa7115.c')
-rw-r--r-- | drivers/media/video/saa7115.c | 763 |
1 files changed, 399 insertions, 364 deletions
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c8e9cb3db30a..22708ecdf1bb 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/i2c.h> | 45 | #include <linux/i2c.h> |
46 | #include <linux/videodev2.h> | 46 | #include <linux/videodev2.h> |
47 | #include <media/v4l2-common.h> | 47 | #include <media/v4l2-device.h> |
48 | #include <media/v4l2-chip-ident.h> | 48 | #include <media/v4l2-chip-ident.h> |
49 | #include <media/v4l2-i2c-drv-legacy.h> | 49 | #include <media/v4l2-i2c-drv-legacy.h> |
50 | #include <media/saa7115.h> | 50 | #include <media/saa7115.h> |
@@ -70,6 +70,7 @@ static unsigned short normal_i2c[] = { | |||
70 | I2C_CLIENT_INSMOD; | 70 | I2C_CLIENT_INSMOD; |
71 | 71 | ||
72 | struct saa711x_state { | 72 | struct saa711x_state { |
73 | struct v4l2_subdev sd; | ||
73 | v4l2_std_id std; | 74 | v4l2_std_id std; |
74 | int input; | 75 | int input; |
75 | int output; | 76 | int output; |
@@ -89,10 +90,17 @@ struct saa711x_state { | |||
89 | u8 apll; | 90 | u8 apll; |
90 | }; | 91 | }; |
91 | 92 | ||
93 | static inline struct saa711x_state *to_state(struct v4l2_subdev *sd) | ||
94 | { | ||
95 | return container_of(sd, struct saa711x_state, sd); | ||
96 | } | ||
97 | |||
92 | /* ----------------------------------------------------------------------- */ | 98 | /* ----------------------------------------------------------------------- */ |
93 | 99 | ||
94 | static inline int saa711x_write(struct i2c_client *client, u8 reg, u8 value) | 100 | static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value) |
95 | { | 101 | { |
102 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
103 | |||
96 | return i2c_smbus_write_byte_data(client, reg, value); | 104 | return i2c_smbus_write_byte_data(client, reg, value); |
97 | } | 105 | } |
98 | 106 | ||
@@ -128,9 +136,9 @@ static int saa711x_has_reg(const int id, const u8 reg) | |||
128 | return 1; | 136 | return 1; |
129 | } | 137 | } |
130 | 138 | ||
131 | static int saa711x_writeregs(struct i2c_client *client, const unsigned char *regs) | 139 | static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs) |
132 | { | 140 | { |
133 | struct saa711x_state *state = i2c_get_clientdata(client); | 141 | struct saa711x_state *state = to_state(sd); |
134 | unsigned char reg, data; | 142 | unsigned char reg, data; |
135 | 143 | ||
136 | while (*regs != 0x00) { | 144 | while (*regs != 0x00) { |
@@ -139,18 +147,20 @@ static int saa711x_writeregs(struct i2c_client *client, const unsigned char *reg | |||
139 | 147 | ||
140 | /* According with datasheets, reserved regs should be | 148 | /* According with datasheets, reserved regs should be |
141 | filled with 0 - seems better not to touch on they */ | 149 | filled with 0 - seems better not to touch on they */ |
142 | if (saa711x_has_reg(state->ident,reg)) { | 150 | if (saa711x_has_reg(state->ident, reg)) { |
143 | if (saa711x_write(client, reg, data) < 0) | 151 | if (saa711x_write(sd, reg, data) < 0) |
144 | return -1; | 152 | return -1; |
145 | } else { | 153 | } else { |
146 | v4l_dbg(1, debug, client, "tried to access reserved reg 0x%02x\n", reg); | 154 | v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg); |
147 | } | 155 | } |
148 | } | 156 | } |
149 | return 0; | 157 | return 0; |
150 | } | 158 | } |
151 | 159 | ||
152 | static inline int saa711x_read(struct i2c_client *client, u8 reg) | 160 | static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg) |
153 | { | 161 | { |
162 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
163 | |||
154 | return i2c_smbus_read_byte_data(client, reg); | 164 | return i2c_smbus_read_byte_data(client, reg); |
155 | } | 165 | } |
156 | 166 | ||
@@ -601,7 +611,7 @@ static int saa711x_odd_parity(u8 c) | |||
601 | return c & 1; | 611 | return c & 1; |
602 | } | 612 | } |
603 | 613 | ||
604 | static int saa711x_decode_vps(u8 * dst, u8 * p) | 614 | static int saa711x_decode_vps(u8 *dst, u8 *p) |
605 | { | 615 | { |
606 | static const u8 biphase_tbl[] = { | 616 | static const u8 biphase_tbl[] = { |
607 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | 617 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, |
@@ -648,7 +658,7 @@ static int saa711x_decode_vps(u8 * dst, u8 * p) | |||
648 | return err & 0xf0; | 658 | return err & 0xf0; |
649 | } | 659 | } |
650 | 660 | ||
651 | static int saa711x_decode_wss(u8 * p) | 661 | static int saa711x_decode_wss(u8 *p) |
652 | { | 662 | { |
653 | static const int wss_bits[8] = { | 663 | static const int wss_bits[8] = { |
654 | 0, 0, 0, 1, 0, 1, 1, 1 | 664 | 0, 0, 0, 1, 0, 1, 1, 1 |
@@ -675,9 +685,9 @@ static int saa711x_decode_wss(u8 * p) | |||
675 | return wss; | 685 | return wss; |
676 | } | 686 | } |
677 | 687 | ||
678 | static int saa711x_set_audio_clock_freq(struct i2c_client *client, u32 freq) | 688 | static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq) |
679 | { | 689 | { |
680 | struct saa711x_state *state = i2c_get_clientdata(client); | 690 | struct saa711x_state *state = to_state(sd); |
681 | u32 acpf; | 691 | u32 acpf; |
682 | u32 acni; | 692 | u32 acni; |
683 | u32 hz; | 693 | u32 hz; |
@@ -685,10 +695,10 @@ static int saa711x_set_audio_clock_freq(struct i2c_client *client, u32 freq) | |||
685 | u8 acc = 0; /* reg 0x3a, audio clock control */ | 695 | u8 acc = 0; /* reg 0x3a, audio clock control */ |
686 | 696 | ||
687 | /* Checks for chips that don't have audio clock (saa7111, saa7113) */ | 697 | /* Checks for chips that don't have audio clock (saa7111, saa7113) */ |
688 | if (!saa711x_has_reg(state->ident,R_30_AUD_MAST_CLK_CYCLES_PER_FIELD)) | 698 | if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD)) |
689 | return 0; | 699 | return 0; |
690 | 700 | ||
691 | v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq); | 701 | v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq); |
692 | 702 | ||
693 | /* sanity check */ | 703 | /* sanity check */ |
694 | if (freq < 32000 || freq > 48000) | 704 | if (freq < 32000 || freq > 48000) |
@@ -715,66 +725,66 @@ static int saa711x_set_audio_clock_freq(struct i2c_client *client, u32 freq) | |||
715 | if (state->apll) | 725 | if (state->apll) |
716 | acc |= 0x08; | 726 | acc |= 0x08; |
717 | 727 | ||
718 | saa711x_write(client, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03); | 728 | saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03); |
719 | saa711x_write(client, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10); | 729 | saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10); |
720 | saa711x_write(client, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc); | 730 | saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc); |
721 | 731 | ||
722 | saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff); | 732 | saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff); |
723 | saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1, | 733 | saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1, |
724 | (acpf >> 8) & 0xff); | 734 | (acpf >> 8) & 0xff); |
725 | saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2, | 735 | saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2, |
726 | (acpf >> 16) & 0x03); | 736 | (acpf >> 16) & 0x03); |
727 | 737 | ||
728 | saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff); | 738 | saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff); |
729 | saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff); | 739 | saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff); |
730 | saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f); | 740 | saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f); |
731 | state->audclk_freq = freq; | 741 | state->audclk_freq = freq; |
732 | return 0; | 742 | return 0; |
733 | } | 743 | } |
734 | 744 | ||
735 | static int saa711x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | 745 | static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
736 | { | 746 | { |
737 | struct saa711x_state *state = i2c_get_clientdata(client); | 747 | struct saa711x_state *state = to_state(sd); |
738 | 748 | ||
739 | switch (ctrl->id) { | 749 | switch (ctrl->id) { |
740 | case V4L2_CID_BRIGHTNESS: | 750 | case V4L2_CID_BRIGHTNESS: |
741 | if (ctrl->value < 0 || ctrl->value > 255) { | 751 | if (ctrl->value < 0 || ctrl->value > 255) { |
742 | v4l_err(client, "invalid brightness setting %d\n", ctrl->value); | 752 | v4l2_err(sd, "invalid brightness setting %d\n", ctrl->value); |
743 | return -ERANGE; | 753 | return -ERANGE; |
744 | } | 754 | } |
745 | 755 | ||
746 | state->bright = ctrl->value; | 756 | state->bright = ctrl->value; |
747 | saa711x_write(client, R_0A_LUMA_BRIGHT_CNTL, state->bright); | 757 | saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, state->bright); |
748 | break; | 758 | break; |
749 | 759 | ||
750 | case V4L2_CID_CONTRAST: | 760 | case V4L2_CID_CONTRAST: |
751 | if (ctrl->value < 0 || ctrl->value > 127) { | 761 | if (ctrl->value < 0 || ctrl->value > 127) { |
752 | v4l_err(client, "invalid contrast setting %d\n", ctrl->value); | 762 | v4l2_err(sd, "invalid contrast setting %d\n", ctrl->value); |
753 | return -ERANGE; | 763 | return -ERANGE; |
754 | } | 764 | } |
755 | 765 | ||
756 | state->contrast = ctrl->value; | 766 | state->contrast = ctrl->value; |
757 | saa711x_write(client, R_0B_LUMA_CONTRAST_CNTL, state->contrast); | 767 | saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, state->contrast); |
758 | break; | 768 | break; |
759 | 769 | ||
760 | case V4L2_CID_SATURATION: | 770 | case V4L2_CID_SATURATION: |
761 | if (ctrl->value < 0 || ctrl->value > 127) { | 771 | if (ctrl->value < 0 || ctrl->value > 127) { |
762 | v4l_err(client, "invalid saturation setting %d\n", ctrl->value); | 772 | v4l2_err(sd, "invalid saturation setting %d\n", ctrl->value); |
763 | return -ERANGE; | 773 | return -ERANGE; |
764 | } | 774 | } |
765 | 775 | ||
766 | state->sat = ctrl->value; | 776 | state->sat = ctrl->value; |
767 | saa711x_write(client, R_0C_CHROMA_SAT_CNTL, state->sat); | 777 | saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, state->sat); |
768 | break; | 778 | break; |
769 | 779 | ||
770 | case V4L2_CID_HUE: | 780 | case V4L2_CID_HUE: |
771 | if (ctrl->value < -127 || ctrl->value > 127) { | 781 | if (ctrl->value < -127 || ctrl->value > 127) { |
772 | v4l_err(client, "invalid hue setting %d\n", ctrl->value); | 782 | v4l2_err(sd, "invalid hue setting %d\n", ctrl->value); |
773 | return -ERANGE; | 783 | return -ERANGE; |
774 | } | 784 | } |
775 | 785 | ||
776 | state->hue = ctrl->value; | 786 | state->hue = ctrl->value; |
777 | saa711x_write(client, R_0D_CHROMA_HUE_CNTL, state->hue); | 787 | saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, state->hue); |
778 | break; | 788 | break; |
779 | 789 | ||
780 | default: | 790 | default: |
@@ -784,9 +794,9 @@ static int saa711x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c | |||
784 | return 0; | 794 | return 0; |
785 | } | 795 | } |
786 | 796 | ||
787 | static int saa711x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | 797 | static int saa711x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
788 | { | 798 | { |
789 | struct saa711x_state *state = i2c_get_clientdata(client); | 799 | struct saa711x_state *state = to_state(sd); |
790 | 800 | ||
791 | switch (ctrl->id) { | 801 | switch (ctrl->id) { |
792 | case V4L2_CID_BRIGHTNESS: | 802 | case V4L2_CID_BRIGHTNESS: |
@@ -808,16 +818,16 @@ static int saa711x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *c | |||
808 | return 0; | 818 | return 0; |
809 | } | 819 | } |
810 | 820 | ||
811 | static int saa711x_set_size(struct i2c_client *client, int width, int height) | 821 | static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height) |
812 | { | 822 | { |
813 | struct saa711x_state *state = i2c_get_clientdata(client); | 823 | struct saa711x_state *state = to_state(sd); |
814 | int HPSC, HFSC; | 824 | int HPSC, HFSC; |
815 | int VSCY; | 825 | int VSCY; |
816 | int res; | 826 | int res; |
817 | int is_50hz = state->std & V4L2_STD_625_50; | 827 | int is_50hz = state->std & V4L2_STD_625_50; |
818 | int Vsrc = is_50hz ? 576 : 480; | 828 | int Vsrc = is_50hz ? 576 : 480; |
819 | 829 | ||
820 | v4l_dbg(1, debug, client, "decoder set size to %ix%i\n",width,height); | 830 | v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height); |
821 | 831 | ||
822 | /* FIXME need better bounds checking here */ | 832 | /* FIXME need better bounds checking here */ |
823 | if ((width < 1) || (width > 1440)) | 833 | if ((width < 1) || (width > 1440)) |
@@ -825,7 +835,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) | |||
825 | if ((height < 1) || (height > Vsrc)) | 835 | if ((height < 1) || (height > Vsrc)) |
826 | return -EINVAL; | 836 | return -EINVAL; |
827 | 837 | ||
828 | if (!saa711x_has_reg(state->ident,R_D0_B_HORIZ_PRESCALING)) { | 838 | if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) { |
829 | /* Decoder only supports 720 columns and 480 or 576 lines */ | 839 | /* Decoder only supports 720 columns and 480 or 576 lines */ |
830 | if (width != 720) | 840 | if (width != 720) |
831 | return -EINVAL; | 841 | return -EINVAL; |
@@ -843,22 +853,22 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) | |||
843 | /* Set output width/height */ | 853 | /* Set output width/height */ |
844 | /* width */ | 854 | /* width */ |
845 | 855 | ||
846 | saa711x_write(client, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, | 856 | saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, |
847 | (u8) (width & 0xff)); | 857 | (u8) (width & 0xff)); |
848 | saa711x_write(client, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, | 858 | saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, |
849 | (u8) ((width >> 8) & 0xff)); | 859 | (u8) ((width >> 8) & 0xff)); |
850 | 860 | ||
851 | /* Vertical Scaling uses height/2 */ | 861 | /* Vertical Scaling uses height/2 */ |
852 | res=height/2; | 862 | res = height / 2; |
853 | 863 | ||
854 | /* On 60Hz, it is using a higher Vertical Output Size */ | 864 | /* On 60Hz, it is using a higher Vertical Output Size */ |
855 | if (!is_50hz) | 865 | if (!is_50hz) |
856 | res += (VRES_60HZ - 480) >> 1; | 866 | res += (VRES_60HZ - 480) >> 1; |
857 | 867 | ||
858 | /* height */ | 868 | /* height */ |
859 | saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, | 869 | saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, |
860 | (u8) (res & 0xff)); | 870 | (u8) (res & 0xff)); |
861 | saa711x_write(client, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB, | 871 | saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB, |
862 | (u8) ((res >> 8) & 0xff)); | 872 | (u8) ((res >> 8) & 0xff)); |
863 | 873 | ||
864 | /* Scaling settings */ | 874 | /* Scaling settings */ |
@@ -869,54 +879,54 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height) | |||
869 | HFSC = (int)((1024 * 720) / (HPSC * width)); | 879 | HFSC = (int)((1024 * 720) / (HPSC * width)); |
870 | /* FIXME hardcodes to "Task B" | 880 | /* FIXME hardcodes to "Task B" |
871 | * write H prescaler integer */ | 881 | * write H prescaler integer */ |
872 | saa711x_write(client, R_D0_B_HORIZ_PRESCALING, | 882 | saa711x_write(sd, R_D0_B_HORIZ_PRESCALING, |
873 | (u8) (HPSC & 0x3f)); | 883 | (u8) (HPSC & 0x3f)); |
874 | 884 | ||
875 | v4l_dbg(1, debug, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC); | 885 | v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC); |
876 | /* write H fine-scaling (luminance) */ | 886 | /* write H fine-scaling (luminance) */ |
877 | saa711x_write(client, R_D8_B_HORIZ_LUMA_SCALING_INC, | 887 | saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC, |
878 | (u8) (HFSC & 0xff)); | 888 | (u8) (HFSC & 0xff)); |
879 | saa711x_write(client, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, | 889 | saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, |
880 | (u8) ((HFSC >> 8) & 0xff)); | 890 | (u8) ((HFSC >> 8) & 0xff)); |
881 | /* write H fine-scaling (chrominance) | 891 | /* write H fine-scaling (chrominance) |
882 | * must be lum/2, so i'll just bitshift :) */ | 892 | * must be lum/2, so i'll just bitshift :) */ |
883 | saa711x_write(client, R_DC_B_HORIZ_CHROMA_SCALING, | 893 | saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING, |
884 | (u8) ((HFSC >> 1) & 0xff)); | 894 | (u8) ((HFSC >> 1) & 0xff)); |
885 | saa711x_write(client, R_DD_B_HORIZ_CHROMA_SCALING_MSB, | 895 | saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB, |
886 | (u8) ((HFSC >> 9) & 0xff)); | 896 | (u8) ((HFSC >> 9) & 0xff)); |
887 | 897 | ||
888 | VSCY = (int)((1024 * Vsrc) / height); | 898 | VSCY = (int)((1024 * Vsrc) / height); |
889 | v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); | 899 | v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); |
890 | 900 | ||
891 | /* Correct Contrast and Luminance */ | 901 | /* Correct Contrast and Luminance */ |
892 | saa711x_write(client, R_D5_B_LUMA_CONTRAST_CNTL, | 902 | saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL, |
893 | (u8) (64 * 1024 / VSCY)); | 903 | (u8) (64 * 1024 / VSCY)); |
894 | saa711x_write(client, R_D6_B_CHROMA_SATURATION_CNTL, | 904 | saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL, |
895 | (u8) (64 * 1024 / VSCY)); | 905 | (u8) (64 * 1024 / VSCY)); |
896 | 906 | ||
897 | /* write V fine-scaling (luminance) */ | 907 | /* write V fine-scaling (luminance) */ |
898 | saa711x_write(client, R_E0_B_VERT_LUMA_SCALING_INC, | 908 | saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC, |
899 | (u8) (VSCY & 0xff)); | 909 | (u8) (VSCY & 0xff)); |
900 | saa711x_write(client, R_E1_B_VERT_LUMA_SCALING_INC_MSB, | 910 | saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB, |
901 | (u8) ((VSCY >> 8) & 0xff)); | 911 | (u8) ((VSCY >> 8) & 0xff)); |
902 | /* write V fine-scaling (chrominance) */ | 912 | /* write V fine-scaling (chrominance) */ |
903 | saa711x_write(client, R_E2_B_VERT_CHROMA_SCALING_INC, | 913 | saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC, |
904 | (u8) (VSCY & 0xff)); | 914 | (u8) (VSCY & 0xff)); |
905 | saa711x_write(client, R_E3_B_VERT_CHROMA_SCALING_INC_MSB, | 915 | saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB, |
906 | (u8) ((VSCY >> 8) & 0xff)); | 916 | (u8) ((VSCY >> 8) & 0xff)); |
907 | 917 | ||
908 | saa711x_writeregs(client, saa7115_cfg_reset_scaler); | 918 | saa711x_writeregs(sd, saa7115_cfg_reset_scaler); |
909 | 919 | ||
910 | /* Activates task "B" */ | 920 | /* Activates task "B" */ |
911 | saa711x_write(client, R_80_GLOBAL_CNTL_1, | 921 | saa711x_write(sd, R_80_GLOBAL_CNTL_1, |
912 | saa711x_read(client,R_80_GLOBAL_CNTL_1) | 0x20); | 922 | saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20); |
913 | 923 | ||
914 | return 0; | 924 | return 0; |
915 | } | 925 | } |
916 | 926 | ||
917 | static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) | 927 | static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) |
918 | { | 928 | { |
919 | struct saa711x_state *state = i2c_get_clientdata(client); | 929 | struct saa711x_state *state = to_state(sd); |
920 | 930 | ||
921 | /* Prevent unnecessary standard changes. During a standard | 931 | /* Prevent unnecessary standard changes. During a standard |
922 | change the I-Port is temporarily disabled. Any devices | 932 | change the I-Port is temporarily disabled. Any devices |
@@ -932,13 +942,13 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) | |||
932 | 942 | ||
933 | // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. | 943 | // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. |
934 | if (std & V4L2_STD_525_60) { | 944 | if (std & V4L2_STD_525_60) { |
935 | v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n"); | 945 | v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n"); |
936 | saa711x_writeregs(client, saa7115_cfg_60hz_video); | 946 | saa711x_writeregs(sd, saa7115_cfg_60hz_video); |
937 | saa711x_set_size(client, 720, 480); | 947 | saa711x_set_size(sd, 720, 480); |
938 | } else { | 948 | } else { |
939 | v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n"); | 949 | v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n"); |
940 | saa711x_writeregs(client, saa7115_cfg_50hz_video); | 950 | saa711x_writeregs(sd, saa7115_cfg_50hz_video); |
941 | saa711x_set_size(client, 720, 576); | 951 | saa711x_set_size(sd, 720, 576); |
942 | } | 952 | } |
943 | 953 | ||
944 | /* Register 0E - Bits D6-D4 on NO-AUTO mode | 954 | /* Register 0E - Bits D6-D4 on NO-AUTO mode |
@@ -952,7 +962,7 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) | |||
952 | */ | 962 | */ |
953 | if (state->ident == V4L2_IDENT_SAA7111 || | 963 | if (state->ident == V4L2_IDENT_SAA7111 || |
954 | state->ident == V4L2_IDENT_SAA7113) { | 964 | state->ident == V4L2_IDENT_SAA7113) { |
955 | u8 reg = saa711x_read(client, R_0E_CHROMA_CNTL_1) & 0x8f; | 965 | u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f; |
956 | 966 | ||
957 | if (std == V4L2_STD_PAL_M) { | 967 | if (std == V4L2_STD_PAL_M) { |
958 | reg |= 0x30; | 968 | reg |= 0x30; |
@@ -965,87 +975,31 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std) | |||
965 | } else if (std & V4L2_STD_SECAM) { | 975 | } else if (std & V4L2_STD_SECAM) { |
966 | reg |= 0x50; | 976 | reg |= 0x50; |
967 | } | 977 | } |
968 | saa711x_write(client, R_0E_CHROMA_CNTL_1, reg); | 978 | saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg); |
969 | } else { | 979 | } else { |
970 | /* restart task B if needed */ | 980 | /* restart task B if needed */ |
971 | int taskb = saa711x_read(client, R_80_GLOBAL_CNTL_1) & 0x10; | 981 | int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10; |
972 | 982 | ||
973 | if (taskb && state->ident == V4L2_IDENT_SAA7114) { | 983 | if (taskb && state->ident == V4L2_IDENT_SAA7114) { |
974 | saa711x_writeregs(client, saa7115_cfg_vbi_on); | 984 | saa711x_writeregs(sd, saa7115_cfg_vbi_on); |
975 | } | 985 | } |
976 | 986 | ||
977 | /* switch audio mode too! */ | 987 | /* switch audio mode too! */ |
978 | saa711x_set_audio_clock_freq(client, state->audclk_freq); | 988 | saa711x_s_clock_freq(sd, state->audclk_freq); |
979 | } | ||
980 | } | ||
981 | |||
982 | static v4l2_std_id saa711x_get_v4lstd(struct i2c_client *client) | ||
983 | { | ||
984 | struct saa711x_state *state = i2c_get_clientdata(client); | ||
985 | |||
986 | return state->std; | ||
987 | } | ||
988 | |||
989 | static void saa711x_log_status(struct i2c_client *client) | ||
990 | { | ||
991 | struct saa711x_state *state = i2c_get_clientdata(client); | ||
992 | int reg1e, reg1f; | ||
993 | int signalOk; | ||
994 | int vcr; | ||
995 | |||
996 | v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq); | ||
997 | if (state->ident != V4L2_IDENT_SAA7115) { | ||
998 | /* status for the saa7114 */ | ||
999 | reg1f = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC); | ||
1000 | signalOk = (reg1f & 0xc1) == 0x81; | ||
1001 | v4l_info(client, "Video signal: %s\n", signalOk ? "ok" : "bad"); | ||
1002 | v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); | ||
1003 | return; | ||
1004 | } | ||
1005 | |||
1006 | /* status for the saa7115 */ | ||
1007 | reg1e = saa711x_read(client, R_1E_STATUS_BYTE_1_VD_DEC); | ||
1008 | reg1f = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC); | ||
1009 | |||
1010 | signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80; | ||
1011 | vcr = !(reg1f & 0x10); | ||
1012 | |||
1013 | if (state->input >= 6) { | ||
1014 | v4l_info(client, "Input: S-Video %d\n", state->input - 6); | ||
1015 | } else { | ||
1016 | v4l_info(client, "Input: Composite %d\n", state->input); | ||
1017 | } | 989 | } |
1018 | v4l_info(client, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); | ||
1019 | v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); | ||
1020 | |||
1021 | switch (reg1e & 0x03) { | ||
1022 | case 1: | ||
1023 | v4l_info(client, "Detected format: NTSC\n"); | ||
1024 | break; | ||
1025 | case 2: | ||
1026 | v4l_info(client, "Detected format: PAL\n"); | ||
1027 | break; | ||
1028 | case 3: | ||
1029 | v4l_info(client, "Detected format: SECAM\n"); | ||
1030 | break; | ||
1031 | default: | ||
1032 | v4l_info(client, "Detected format: BW/No color\n"); | ||
1033 | break; | ||
1034 | } | ||
1035 | v4l_info(client, "Width, Height: %d, %d\n", state->width, state->height); | ||
1036 | } | 990 | } |
1037 | 991 | ||
1038 | /* setup the sliced VBI lcr registers according to the sliced VBI format */ | 992 | /* setup the sliced VBI lcr registers according to the sliced VBI format */ |
1039 | static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_format *fmt) | 993 | static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt) |
1040 | { | 994 | { |
1041 | struct saa711x_state *state = i2c_get_clientdata(client); | 995 | struct saa711x_state *state = to_state(sd); |
1042 | int is_50hz = (state->std & V4L2_STD_625_50); | 996 | int is_50hz = (state->std & V4L2_STD_625_50); |
1043 | u8 lcr[24]; | 997 | u8 lcr[24]; |
1044 | int i, x; | 998 | int i, x; |
1045 | 999 | ||
1046 | #if 1 | 1000 | #if 1 |
1047 | /* saa7113/7114/7118 VBI support are experimental */ | 1001 | /* saa7113/7114/7118 VBI support are experimental */ |
1048 | if (!saa711x_has_reg(state->ident,R_41_LCR_BASE)) | 1002 | if (!saa711x_has_reg(state->ident, R_41_LCR_BASE)) |
1049 | return; | 1003 | return; |
1050 | 1004 | ||
1051 | #else | 1005 | #else |
@@ -1109,16 +1063,16 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo | |||
1109 | 1063 | ||
1110 | /* write the lcr registers */ | 1064 | /* write the lcr registers */ |
1111 | for (i = 2; i <= 23; i++) { | 1065 | for (i = 2; i <= 23; i++) { |
1112 | saa711x_write(client, i - 2 + R_41_LCR_BASE, lcr[i]); | 1066 | saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]); |
1113 | } | 1067 | } |
1114 | 1068 | ||
1115 | /* enable/disable raw VBI capturing */ | 1069 | /* enable/disable raw VBI capturing */ |
1116 | saa711x_writeregs(client, fmt == NULL ? | 1070 | saa711x_writeregs(sd, fmt == NULL ? |
1117 | saa7115_cfg_vbi_on : | 1071 | saa7115_cfg_vbi_on : |
1118 | saa7115_cfg_vbi_off); | 1072 | saa7115_cfg_vbi_off); |
1119 | } | 1073 | } |
1120 | 1074 | ||
1121 | static int saa711x_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | 1075 | static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) |
1122 | { | 1076 | { |
1123 | static u16 lcr2vbi[] = { | 1077 | static u16 lcr2vbi[] = { |
1124 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ | 1078 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ |
@@ -1134,10 +1088,10 @@ static int saa711x_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt | |||
1134 | return -EINVAL; | 1088 | return -EINVAL; |
1135 | memset(sliced, 0, sizeof(*sliced)); | 1089 | memset(sliced, 0, sizeof(*sliced)); |
1136 | /* done if using raw VBI */ | 1090 | /* done if using raw VBI */ |
1137 | if (saa711x_read(client, R_80_GLOBAL_CNTL_1) & 0x10) | 1091 | if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10) |
1138 | return 0; | 1092 | return 0; |
1139 | for (i = 2; i <= 23; i++) { | 1093 | for (i = 2; i <= 23; i++) { |
1140 | u8 v = saa711x_read(client, i - 2 + R_41_LCR_BASE); | 1094 | u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE); |
1141 | 1095 | ||
1142 | sliced->service_lines[0][i] = lcr2vbi[v >> 4]; | 1096 | sliced->service_lines[0][i] = lcr2vbi[v >> 4]; |
1143 | sliced->service_lines[1][i] = lcr2vbi[v & 0xf]; | 1097 | sliced->service_lines[1][i] = lcr2vbi[v & 0xf]; |
@@ -1147,20 +1101,20 @@ static int saa711x_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt | |||
1147 | return 0; | 1101 | return 0; |
1148 | } | 1102 | } |
1149 | 1103 | ||
1150 | static int saa711x_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | 1104 | static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) |
1151 | { | 1105 | { |
1152 | if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | 1106 | if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { |
1153 | saa711x_set_lcr(client, &fmt->fmt.sliced); | 1107 | saa711x_set_lcr(sd, &fmt->fmt.sliced); |
1154 | return 0; | 1108 | return 0; |
1155 | } | 1109 | } |
1156 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | 1110 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
1157 | saa711x_set_lcr(client, NULL); | 1111 | saa711x_set_lcr(sd, NULL); |
1158 | return 0; | 1112 | return 0; |
1159 | } | 1113 | } |
1160 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1114 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1161 | return -EINVAL; | 1115 | return -EINVAL; |
1162 | 1116 | ||
1163 | return saa711x_set_size(client,fmt->fmt.pix.width,fmt->fmt.pix.height); | 1117 | return saa711x_set_size(sd, fmt->fmt.pix.width, fmt->fmt.pix.height); |
1164 | } | 1118 | } |
1165 | 1119 | ||
1166 | /* Decode the sliced VBI data stream as created by the saa7115. | 1120 | /* Decode the sliced VBI data stream as created by the saa7115. |
@@ -1169,13 +1123,12 @@ static int saa711x_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt | |||
1169 | The current implementation uses SAV/EAV codes and not the ancillary data | 1123 | The current implementation uses SAV/EAV codes and not the ancillary data |
1170 | headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV | 1124 | headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV |
1171 | code. */ | 1125 | code. */ |
1172 | static void saa711x_decode_vbi_line(struct i2c_client *client, | 1126 | static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi) |
1173 | struct v4l2_decode_vbi_line *vbi) | ||
1174 | { | 1127 | { |
1128 | struct saa711x_state *state = to_state(sd); | ||
1175 | static const char vbi_no_data_pattern[] = { | 1129 | static const char vbi_no_data_pattern[] = { |
1176 | 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0 | 1130 | 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0 |
1177 | }; | 1131 | }; |
1178 | struct saa711x_state *state = i2c_get_clientdata(client); | ||
1179 | u8 *p = vbi->p; | 1132 | u8 *p = vbi->p; |
1180 | u32 wss; | 1133 | u32 wss; |
1181 | int id1, id2; /* the ID1 and ID2 bytes from the internal header */ | 1134 | int id1, id2; /* the ID1 and ID2 bytes from the internal header */ |
@@ -1202,7 +1155,7 @@ static void saa711x_decode_vbi_line(struct i2c_client *client, | |||
1202 | /* If the VBI slicer does not detect any signal it will fill up | 1155 | /* If the VBI slicer does not detect any signal it will fill up |
1203 | the payload buffer with 0xa0 bytes. */ | 1156 | the payload buffer with 0xa0 bytes. */ |
1204 | if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern))) | 1157 | if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern))) |
1205 | return; | 1158 | return 0; |
1206 | 1159 | ||
1207 | /* decode payloads */ | 1160 | /* decode payloads */ |
1208 | switch (id2) { | 1161 | switch (id2) { |
@@ -1211,275 +1164,352 @@ static void saa711x_decode_vbi_line(struct i2c_client *client, | |||
1211 | break; | 1164 | break; |
1212 | case 4: | 1165 | case 4: |
1213 | if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1])) | 1166 | if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1])) |
1214 | return; | 1167 | return 0; |
1215 | vbi->type = V4L2_SLICED_CAPTION_525; | 1168 | vbi->type = V4L2_SLICED_CAPTION_525; |
1216 | break; | 1169 | break; |
1217 | case 5: | 1170 | case 5: |
1218 | wss = saa711x_decode_wss(p); | 1171 | wss = saa711x_decode_wss(p); |
1219 | if (wss == -1) | 1172 | if (wss == -1) |
1220 | return; | 1173 | return 0; |
1221 | p[0] = wss & 0xff; | 1174 | p[0] = wss & 0xff; |
1222 | p[1] = wss >> 8; | 1175 | p[1] = wss >> 8; |
1223 | vbi->type = V4L2_SLICED_WSS_625; | 1176 | vbi->type = V4L2_SLICED_WSS_625; |
1224 | break; | 1177 | break; |
1225 | case 7: | 1178 | case 7: |
1226 | if (saa711x_decode_vps(p, p) != 0) | 1179 | if (saa711x_decode_vps(p, p) != 0) |
1227 | return; | 1180 | return 0; |
1228 | vbi->type = V4L2_SLICED_VPS; | 1181 | vbi->type = V4L2_SLICED_VPS; |
1229 | break; | 1182 | break; |
1230 | default: | 1183 | default: |
1231 | return; | 1184 | break; |
1232 | } | 1185 | } |
1186 | return 0; | ||
1233 | } | 1187 | } |
1234 | 1188 | ||
1235 | /* ============ SAA7115 AUDIO settings (end) ============= */ | 1189 | /* ============ SAA7115 AUDIO settings (end) ============= */ |
1236 | 1190 | ||
1237 | static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) | 1191 | static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) |
1238 | { | 1192 | { |
1239 | struct saa711x_state *state = i2c_get_clientdata(client); | 1193 | struct saa711x_state *state = to_state(sd); |
1194 | int status; | ||
1240 | 1195 | ||
1241 | /* ioctls to allow direct access to the saa7115 registers for testing */ | 1196 | if (state->radio) |
1242 | switch (cmd) { | 1197 | return 0; |
1243 | case VIDIOC_S_FMT: | 1198 | status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); |
1244 | return saa711x_set_v4lfmt(client, (struct v4l2_format *)arg); | ||
1245 | 1199 | ||
1246 | case VIDIOC_G_FMT: | 1200 | v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status); |
1247 | return saa711x_get_v4lfmt(client, (struct v4l2_format *)arg); | 1201 | vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0; |
1202 | return 0; | ||
1203 | } | ||
1248 | 1204 | ||
1249 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | 1205 | static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) |
1250 | return saa711x_set_audio_clock_freq(client, *(u32 *)arg); | 1206 | { |
1207 | switch (qc->id) { | ||
1208 | case V4L2_CID_BRIGHTNESS: | ||
1209 | case V4L2_CID_CONTRAST: | ||
1210 | case V4L2_CID_SATURATION: | ||
1211 | case V4L2_CID_HUE: | ||
1212 | return v4l2_ctrl_query_fill_std(qc); | ||
1213 | default: | ||
1214 | return -EINVAL; | ||
1215 | } | ||
1216 | } | ||
1251 | 1217 | ||
1252 | case VIDIOC_G_TUNER: | 1218 | static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std) |
1253 | { | 1219 | { |
1254 | struct v4l2_tuner *vt = arg; | 1220 | struct saa711x_state *state = to_state(sd); |
1255 | int status; | ||
1256 | 1221 | ||
1257 | if (state->radio) | 1222 | state->radio = 0; |
1258 | break; | 1223 | saa711x_set_v4lstd(sd, std); |
1259 | status = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC); | 1224 | return 0; |
1225 | } | ||
1260 | 1226 | ||
1261 | v4l_dbg(1, debug, client, "status: 0x%02x\n", status); | 1227 | static int saa711x_s_radio(struct v4l2_subdev *sd) |
1262 | vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0; | 1228 | { |
1263 | break; | 1229 | struct saa711x_state *state = to_state(sd); |
1264 | } | ||
1265 | 1230 | ||
1266 | case VIDIOC_LOG_STATUS: | 1231 | state->radio = 1; |
1267 | saa711x_log_status(client); | 1232 | return 0; |
1268 | break; | 1233 | } |
1269 | 1234 | ||
1270 | case VIDIOC_G_CTRL: | 1235 | static int saa711x_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) |
1271 | return saa711x_get_v4lctrl(client, (struct v4l2_control *)arg); | 1236 | { |
1237 | struct saa711x_state *state = to_state(sd); | ||
1238 | u32 input = route->input; | ||
1239 | u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0; | ||
1240 | |||
1241 | v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n", route->input, route->output); | ||
1242 | /* saa7111/3 does not have these inputs */ | ||
1243 | if ((state->ident == V4L2_IDENT_SAA7113 || | ||
1244 | state->ident == V4L2_IDENT_SAA7111) && | ||
1245 | (route->input == SAA7115_COMPOSITE4 || | ||
1246 | route->input == SAA7115_COMPOSITE5)) { | ||
1247 | return -EINVAL; | ||
1248 | } | ||
1249 | if (route->input > SAA7115_SVIDEO3) | ||
1250 | return -EINVAL; | ||
1251 | if (route->output > SAA7115_IPORT_ON) | ||
1252 | return -EINVAL; | ||
1253 | if (state->input == route->input && state->output == route->output) | ||
1254 | return 0; | ||
1255 | v4l2_dbg(1, debug, sd, "now setting %s input %s output\n", | ||
1256 | (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", | ||
1257 | (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); | ||
1258 | state->input = route->input; | ||
1259 | |||
1260 | /* saa7111 has slightly different input numbering */ | ||
1261 | if (state->ident == V4L2_IDENT_SAA7111) { | ||
1262 | if (input >= SAA7115_COMPOSITE4) | ||
1263 | input -= 2; | ||
1264 | /* saa7111 specific */ | ||
1265 | saa711x_write(sd, R_10_CHROMA_CNTL_2, | ||
1266 | (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) | | ||
1267 | ((route->output & 0xc0) ^ 0x40)); | ||
1268 | saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL, | ||
1269 | (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) | | ||
1270 | ((route->output & 2) ? 0x0a : 0)); | ||
1271 | } | ||
1272 | 1272 | ||
1273 | case VIDIOC_S_CTRL: | 1273 | /* select mode */ |
1274 | return saa711x_set_v4lctrl(client, (struct v4l2_control *)arg); | 1274 | saa711x_write(sd, R_02_INPUT_CNTL_1, |
1275 | (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) | | ||
1276 | input); | ||
1275 | 1277 | ||
1276 | case VIDIOC_QUERYCTRL: | 1278 | /* bypass chrominance trap for S-Video modes */ |
1277 | { | 1279 | saa711x_write(sd, R_09_LUMA_CNTL, |
1278 | struct v4l2_queryctrl *qc = arg; | 1280 | (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) | |
1281 | (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); | ||
1279 | 1282 | ||
1280 | switch (qc->id) { | 1283 | state->output = route->output; |
1281 | case V4L2_CID_BRIGHTNESS: | 1284 | if (state->ident == V4L2_IDENT_SAA7114 || |
1282 | case V4L2_CID_CONTRAST: | 1285 | state->ident == V4L2_IDENT_SAA7115) { |
1283 | case V4L2_CID_SATURATION: | 1286 | saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, |
1284 | case V4L2_CID_HUE: | 1287 | (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) | |
1285 | return v4l2_ctrl_query_fill_std(qc); | 1288 | (state->output & 0x01)); |
1286 | default: | ||
1287 | return -EINVAL; | ||
1288 | } | ||
1289 | } | 1289 | } |
1290 | return 0; | ||
1291 | } | ||
1290 | 1292 | ||
1291 | case VIDIOC_G_STD: | 1293 | static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val) |
1292 | *(v4l2_std_id *)arg = saa711x_get_v4lstd(client); | 1294 | { |
1293 | break; | 1295 | struct saa711x_state *state = to_state(sd); |
1294 | 1296 | ||
1295 | case VIDIOC_S_STD: | 1297 | if (state->ident != V4L2_IDENT_SAA7111) |
1296 | state->radio = 0; | 1298 | return -EINVAL; |
1297 | saa711x_set_v4lstd(client, *(v4l2_std_id *)arg); | 1299 | saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) | |
1298 | break; | 1300 | (val ? 0x80 : 0)); |
1301 | return 0; | ||
1302 | } | ||
1299 | 1303 | ||
1300 | case AUDC_SET_RADIO: | 1304 | static int saa711x_s_stream(struct v4l2_subdev *sd, int enable) |
1301 | state->radio = 1; | 1305 | { |
1302 | break; | 1306 | struct saa711x_state *state = to_state(sd); |
1303 | 1307 | ||
1304 | case VIDIOC_INT_G_VIDEO_ROUTING: | 1308 | v4l2_dbg(1, debug, sd, "%s output\n", |
1305 | { | 1309 | enable ? "enable" : "disable"); |
1306 | struct v4l2_routing *route = arg; | ||
1307 | 1310 | ||
1308 | route->input = state->input; | 1311 | if (state->enable != enable) { |
1309 | route->output = state->output; | 1312 | state->enable = enable; |
1310 | break; | 1313 | saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, |
1314 | state->enable); | ||
1311 | } | 1315 | } |
1316 | return 0; | ||
1317 | } | ||
1312 | 1318 | ||
1313 | case VIDIOC_INT_S_VIDEO_ROUTING: | 1319 | static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, struct v4l2_crystal_freq *freq) |
1314 | { | 1320 | { |
1315 | struct v4l2_routing *route = arg; | 1321 | struct saa711x_state *state = to_state(sd); |
1316 | u32 input = route->input; | ||
1317 | u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0; | ||
1318 | |||
1319 | v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output); | ||
1320 | /* saa7111/3 does not have these inputs */ | ||
1321 | if ((state->ident == V4L2_IDENT_SAA7113 || | ||
1322 | state->ident == V4L2_IDENT_SAA7111) && | ||
1323 | (route->input == SAA7115_COMPOSITE4 || | ||
1324 | route->input == SAA7115_COMPOSITE5)) { | ||
1325 | return -EINVAL; | ||
1326 | } | ||
1327 | if (route->input > SAA7115_SVIDEO3) | ||
1328 | return -EINVAL; | ||
1329 | if (route->output > SAA7115_IPORT_ON) | ||
1330 | return -EINVAL; | ||
1331 | if (state->input == route->input && state->output == route->output) | ||
1332 | break; | ||
1333 | v4l_dbg(1, debug, client, "now setting %s input %s output\n", | ||
1334 | (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); | ||
1335 | state->input = route->input; | ||
1336 | |||
1337 | /* saa7111 has slightly different input numbering */ | ||
1338 | if (state->ident == V4L2_IDENT_SAA7111) { | ||
1339 | if (input >= SAA7115_COMPOSITE4) | ||
1340 | input -= 2; | ||
1341 | /* saa7111 specific */ | ||
1342 | saa711x_write(client, R_10_CHROMA_CNTL_2, | ||
1343 | (saa711x_read(client, R_10_CHROMA_CNTL_2) & 0x3f) | | ||
1344 | ((route->output & 0xc0) ^ 0x40)); | ||
1345 | saa711x_write(client, R_13_RT_X_PORT_OUT_CNTL, | ||
1346 | (saa711x_read(client, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) | | ||
1347 | ((route->output & 2) ? 0x0a : 0)); | ||
1348 | } | ||
1349 | 1322 | ||
1350 | /* select mode */ | 1323 | if (freq->freq != SAA7115_FREQ_32_11_MHZ && |
1351 | saa711x_write(client, R_02_INPUT_CNTL_1, | 1324 | freq->freq != SAA7115_FREQ_24_576_MHZ) |
1352 | (saa711x_read(client, R_02_INPUT_CNTL_1) & mask) | | 1325 | return -EINVAL; |
1353 | input); | 1326 | state->crystal_freq = freq->freq; |
1327 | state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4; | ||
1328 | state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0; | ||
1329 | state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0; | ||
1330 | saa711x_s_clock_freq(sd, state->audclk_freq); | ||
1331 | return 0; | ||
1332 | } | ||
1354 | 1333 | ||
1355 | /* bypass chrominance trap for S-Video modes */ | 1334 | static int saa711x_reset(struct v4l2_subdev *sd, u32 val) |
1356 | saa711x_write(client, R_09_LUMA_CNTL, | 1335 | { |
1357 | (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) | | 1336 | v4l2_dbg(1, debug, sd, "decoder RESET\n"); |
1358 | (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); | 1337 | saa711x_writeregs(sd, saa7115_cfg_reset_scaler); |
1338 | return 0; | ||
1339 | } | ||
1359 | 1340 | ||
1360 | state->output = route->output; | 1341 | static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data) |
1361 | if (state->ident == V4L2_IDENT_SAA7114 || | 1342 | { |
1362 | state->ident == V4L2_IDENT_SAA7115) { | 1343 | /* Note: the internal field ID is inverted for NTSC, |
1363 | saa711x_write(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, | 1344 | so data->field 0 maps to the saa7115 even field, |
1364 | (saa711x_read(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) | | 1345 | whereas for PAL it maps to the saa7115 odd field. */ |
1365 | (state->output & 0x01)); | 1346 | switch (data->id) { |
1347 | case V4L2_SLICED_WSS_625: | ||
1348 | if (saa711x_read(sd, 0x6b) & 0xc0) | ||
1349 | return -EIO; | ||
1350 | data->data[0] = saa711x_read(sd, 0x6c); | ||
1351 | data->data[1] = saa711x_read(sd, 0x6d); | ||
1352 | return 0; | ||
1353 | case V4L2_SLICED_CAPTION_525: | ||
1354 | if (data->field == 0) { | ||
1355 | /* CC */ | ||
1356 | if (saa711x_read(sd, 0x66) & 0x30) | ||
1357 | return -EIO; | ||
1358 | data->data[0] = saa711x_read(sd, 0x69); | ||
1359 | data->data[1] = saa711x_read(sd, 0x6a); | ||
1360 | return 0; | ||
1366 | } | 1361 | } |
1367 | break; | 1362 | /* XDS */ |
1363 | if (saa711x_read(sd, 0x66) & 0xc0) | ||
1364 | return -EIO; | ||
1365 | data->data[0] = saa711x_read(sd, 0x67); | ||
1366 | data->data[1] = saa711x_read(sd, 0x68); | ||
1367 | return 0; | ||
1368 | default: | ||
1369 | return -EINVAL; | ||
1368 | } | 1370 | } |
1371 | } | ||
1369 | 1372 | ||
1370 | case VIDIOC_STREAMON: | 1373 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1371 | case VIDIOC_STREAMOFF: | 1374 | static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) |
1372 | v4l_dbg(1, debug, client, "%s output\n", | 1375 | { |
1373 | (cmd == VIDIOC_STREAMON) ? "enable" : "disable"); | 1376 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1374 | |||
1375 | if (state->enable != (cmd == VIDIOC_STREAMON)) { | ||
1376 | state->enable = (cmd == VIDIOC_STREAMON); | ||
1377 | saa711x_write(client, | ||
1378 | R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, | ||
1379 | state->enable); | ||
1380 | } | ||
1381 | break; | ||
1382 | 1377 | ||
1383 | case VIDIOC_INT_S_CRYSTAL_FREQ: | 1378 | if (!v4l2_chip_match_i2c_client(client, |
1384 | { | 1379 | reg->match_type, reg->match_chip)) |
1385 | struct v4l2_crystal_freq *freq = arg; | 1380 | return -EINVAL; |
1381 | if (!capable(CAP_SYS_ADMIN)) | ||
1382 | return -EPERM; | ||
1383 | reg->val = saa711x_read(sd, reg->reg & 0xff); | ||
1384 | return 0; | ||
1385 | } | ||
1386 | 1386 | ||
1387 | if (freq->freq != SAA7115_FREQ_32_11_MHZ && | 1387 | static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) |
1388 | freq->freq != SAA7115_FREQ_24_576_MHZ) | 1388 | { |
1389 | return -EINVAL; | 1389 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1390 | state->crystal_freq = freq->freq; | ||
1391 | state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4; | ||
1392 | state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0; | ||
1393 | state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0; | ||
1394 | saa711x_set_audio_clock_freq(client, state->audclk_freq); | ||
1395 | break; | ||
1396 | } | ||
1397 | 1390 | ||
1398 | case VIDIOC_INT_DECODE_VBI_LINE: | 1391 | if (!v4l2_chip_match_i2c_client(client, |
1399 | saa711x_decode_vbi_line(client, arg); | 1392 | reg->match_type, reg->match_chip)) |
1400 | break; | 1393 | return -EINVAL; |
1394 | if (!capable(CAP_SYS_ADMIN)) | ||
1395 | return -EPERM; | ||
1396 | saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff); | ||
1397 | return 0; | ||
1398 | } | ||
1399 | #endif | ||
1401 | 1400 | ||
1402 | case VIDIOC_INT_RESET: | 1401 | static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) |
1403 | v4l_dbg(1, debug, client, "decoder RESET\n"); | 1402 | { |
1404 | saa711x_writeregs(client, saa7115_cfg_reset_scaler); | 1403 | struct saa711x_state *state = to_state(sd); |
1405 | break; | 1404 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1406 | 1405 | ||
1407 | case VIDIOC_INT_S_GPIO: | 1406 | return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0); |
1408 | if (state->ident != V4L2_IDENT_SAA7111) | 1407 | } |
1409 | return -EINVAL; | ||
1410 | saa711x_write(client, 0x11, (saa711x_read(client, 0x11) & 0x7f) | | ||
1411 | (*(u32 *)arg ? 0x80 : 0)); | ||
1412 | break; | ||
1413 | 1408 | ||
1414 | case VIDIOC_INT_G_VBI_DATA: | 1409 | static int saa711x_log_status(struct v4l2_subdev *sd) |
1415 | { | 1410 | { |
1416 | struct v4l2_sliced_vbi_data *data = arg; | 1411 | struct saa711x_state *state = to_state(sd); |
1412 | int reg1e, reg1f; | ||
1413 | int signalOk; | ||
1414 | int vcr; | ||
1417 | 1415 | ||
1418 | /* Note: the internal field ID is inverted for NTSC, | 1416 | v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq); |
1419 | so data->field 0 maps to the saa7115 even field, | 1417 | if (state->ident != V4L2_IDENT_SAA7115) { |
1420 | whereas for PAL it maps to the saa7115 odd field. */ | 1418 | /* status for the saa7114 */ |
1421 | switch (data->id) { | 1419 | reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); |
1422 | case V4L2_SLICED_WSS_625: | 1420 | signalOk = (reg1f & 0xc1) == 0x81; |
1423 | if (saa711x_read(client, 0x6b) & 0xc0) | 1421 | v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad"); |
1424 | return -EIO; | 1422 | v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); |
1425 | data->data[0] = saa711x_read(client, 0x6c); | 1423 | return 0; |
1426 | data->data[1] = saa711x_read(client, 0x6d); | ||
1427 | return 0; | ||
1428 | case V4L2_SLICED_CAPTION_525: | ||
1429 | if (data->field == 0) { | ||
1430 | /* CC */ | ||
1431 | if (saa711x_read(client, 0x66) & 0x30) | ||
1432 | return -EIO; | ||
1433 | data->data[0] = saa711x_read(client, 0x69); | ||
1434 | data->data[1] = saa711x_read(client, 0x6a); | ||
1435 | return 0; | ||
1436 | } | ||
1437 | /* XDS */ | ||
1438 | if (saa711x_read(client, 0x66) & 0xc0) | ||
1439 | return -EIO; | ||
1440 | data->data[0] = saa711x_read(client, 0x67); | ||
1441 | data->data[1] = saa711x_read(client, 0x68); | ||
1442 | return 0; | ||
1443 | default: | ||
1444 | return -EINVAL; | ||
1445 | } | ||
1446 | break; | ||
1447 | } | 1424 | } |
1448 | 1425 | ||
1449 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1426 | /* status for the saa7115 */ |
1450 | case VIDIOC_DBG_G_REGISTER: | 1427 | reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); |
1451 | case VIDIOC_DBG_S_REGISTER: | 1428 | reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); |
1452 | { | ||
1453 | struct v4l2_register *reg = arg; | ||
1454 | 1429 | ||
1455 | if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) | 1430 | signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80; |
1456 | return -EINVAL; | 1431 | vcr = !(reg1f & 0x10); |
1457 | if (!capable(CAP_SYS_ADMIN)) | ||
1458 | return -EPERM; | ||
1459 | if (cmd == VIDIOC_DBG_G_REGISTER) | ||
1460 | reg->val = saa711x_read(client, reg->reg & 0xff); | ||
1461 | else | ||
1462 | saa711x_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
1463 | break; | ||
1464 | } | ||
1465 | #endif | ||
1466 | 1432 | ||
1467 | case VIDIOC_G_CHIP_IDENT: | 1433 | if (state->input >= 6) |
1468 | return v4l2_chip_ident_i2c_client(client, arg, state->ident, 0); | 1434 | v4l2_info(sd, "Input: S-Video %d\n", state->input - 6); |
1435 | else | ||
1436 | v4l2_info(sd, "Input: Composite %d\n", state->input); | ||
1437 | v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); | ||
1438 | v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz"); | ||
1469 | 1439 | ||
1440 | switch (reg1e & 0x03) { | ||
1441 | case 1: | ||
1442 | v4l2_info(sd, "Detected format: NTSC\n"); | ||
1443 | break; | ||
1444 | case 2: | ||
1445 | v4l2_info(sd, "Detected format: PAL\n"); | ||
1446 | break; | ||
1447 | case 3: | ||
1448 | v4l2_info(sd, "Detected format: SECAM\n"); | ||
1449 | break; | ||
1470 | default: | 1450 | default: |
1471 | return -EINVAL; | 1451 | v4l2_info(sd, "Detected format: BW/No color\n"); |
1452 | break; | ||
1472 | } | 1453 | } |
1473 | 1454 | v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height); | |
1474 | return 0; | 1455 | return 0; |
1475 | } | 1456 | } |
1476 | 1457 | ||
1458 | static int saa711x_command(struct i2c_client *client, unsigned cmd, void *arg) | ||
1459 | { | ||
1460 | return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); | ||
1461 | } | ||
1462 | |||
1463 | /* ----------------------------------------------------------------------- */ | ||
1464 | |||
1465 | static const struct v4l2_subdev_core_ops saa711x_core_ops = { | ||
1466 | .log_status = saa711x_log_status, | ||
1467 | .g_chip_ident = saa711x_g_chip_ident, | ||
1468 | .g_ctrl = saa711x_g_ctrl, | ||
1469 | .s_ctrl = saa711x_s_ctrl, | ||
1470 | .queryctrl = saa711x_queryctrl, | ||
1471 | .reset = saa711x_reset, | ||
1472 | .s_gpio = saa711x_s_gpio, | ||
1473 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1474 | .g_register = saa711x_g_register, | ||
1475 | .s_register = saa711x_s_register, | ||
1476 | #endif | ||
1477 | }; | ||
1478 | |||
1479 | static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = { | ||
1480 | .s_std = saa711x_s_std, | ||
1481 | .s_radio = saa711x_s_radio, | ||
1482 | .g_tuner = saa711x_g_tuner, | ||
1483 | }; | ||
1484 | |||
1485 | static const struct v4l2_subdev_audio_ops saa711x_audio_ops = { | ||
1486 | .s_clock_freq = saa711x_s_clock_freq, | ||
1487 | }; | ||
1488 | |||
1489 | static const struct v4l2_subdev_video_ops saa711x_video_ops = { | ||
1490 | .s_routing = saa711x_s_routing, | ||
1491 | .s_crystal_freq = saa711x_s_crystal_freq, | ||
1492 | .g_fmt = saa711x_g_fmt, | ||
1493 | .s_fmt = saa711x_s_fmt, | ||
1494 | .g_vbi_data = saa711x_g_vbi_data, | ||
1495 | .decode_vbi_line = saa711x_decode_vbi_line, | ||
1496 | .s_stream = saa711x_s_stream, | ||
1497 | }; | ||
1498 | |||
1499 | static const struct v4l2_subdev_ops saa711x_ops = { | ||
1500 | .core = &saa711x_core_ops, | ||
1501 | .tuner = &saa711x_tuner_ops, | ||
1502 | .audio = &saa711x_audio_ops, | ||
1503 | .video = &saa711x_video_ops, | ||
1504 | }; | ||
1505 | |||
1477 | /* ----------------------------------------------------------------------- */ | 1506 | /* ----------------------------------------------------------------------- */ |
1478 | 1507 | ||
1479 | static int saa7115_probe(struct i2c_client *client, | 1508 | static int saa711x_probe(struct i2c_client *client, |
1480 | const struct i2c_device_id *id) | 1509 | const struct i2c_device_id *id) |
1481 | { | 1510 | { |
1482 | struct saa711x_state *state; | 1511 | struct saa711x_state *state; |
1512 | struct v4l2_subdev *sd; | ||
1483 | int i; | 1513 | int i; |
1484 | char name[17]; | 1514 | char name[17]; |
1485 | char chip_id; | 1515 | char chip_id; |
@@ -1490,8 +1520,8 @@ static int saa7115_probe(struct i2c_client *client, | |||
1490 | return -EIO; | 1520 | return -EIO; |
1491 | 1521 | ||
1492 | for (i = 0; i < 0x0f; i++) { | 1522 | for (i = 0; i < 0x0f; i++) { |
1493 | saa711x_write(client, 0, i); | 1523 | i2c_smbus_write_byte_data(client, 0, i); |
1494 | name[i] = (saa711x_read(client, 0) & 0x0f) + '0'; | 1524 | name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0'; |
1495 | if (name[i] > '9') | 1525 | if (name[i] > '9') |
1496 | name[i] += 'a' - '9' - 1; | 1526 | name[i] += 'a' - '9' - 1; |
1497 | } | 1527 | } |
@@ -1518,7 +1548,8 @@ static int saa7115_probe(struct i2c_client *client, | |||
1518 | state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL); | 1548 | state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL); |
1519 | if (state == NULL) | 1549 | if (state == NULL) |
1520 | return -ENOMEM; | 1550 | return -ENOMEM; |
1521 | i2c_set_clientdata(client, state); | 1551 | sd = &state->sd; |
1552 | v4l2_i2c_subdev_init(sd, client, &saa711x_ops); | ||
1522 | state->input = -1; | 1553 | state->input = -1; |
1523 | state->output = SAA7115_IPORT_ON; | 1554 | state->output = SAA7115_IPORT_ON; |
1524 | state->enable = 1; | 1555 | state->enable = 1; |
@@ -1545,41 +1576,45 @@ static int saa7115_probe(struct i2c_client *client, | |||
1545 | break; | 1576 | break; |
1546 | default: | 1577 | default: |
1547 | state->ident = V4L2_IDENT_SAA7111; | 1578 | state->ident = V4L2_IDENT_SAA7111; |
1548 | v4l_info(client, "WARNING: Chip is not known - Falling back to saa7111\n"); | 1579 | v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n"); |
1549 | 1580 | ||
1550 | } | 1581 | } |
1551 | 1582 | ||
1552 | state->audclk_freq = 48000; | 1583 | state->audclk_freq = 48000; |
1553 | 1584 | ||
1554 | v4l_dbg(1, debug, client, "writing init values\n"); | 1585 | v4l2_dbg(1, debug, sd, "writing init values\n"); |
1555 | 1586 | ||
1556 | /* init to 60hz/48khz */ | 1587 | /* init to 60hz/48khz */ |
1557 | state->crystal_freq = SAA7115_FREQ_24_576_MHZ; | 1588 | state->crystal_freq = SAA7115_FREQ_24_576_MHZ; |
1558 | switch (state->ident) { | 1589 | switch (state->ident) { |
1559 | case V4L2_IDENT_SAA7111: | 1590 | case V4L2_IDENT_SAA7111: |
1560 | saa711x_writeregs(client, saa7111_init); | 1591 | saa711x_writeregs(sd, saa7111_init); |
1561 | break; | 1592 | break; |
1562 | case V4L2_IDENT_SAA7113: | 1593 | case V4L2_IDENT_SAA7113: |
1563 | saa711x_writeregs(client, saa7113_init); | 1594 | saa711x_writeregs(sd, saa7113_init); |
1564 | break; | 1595 | break; |
1565 | default: | 1596 | default: |
1566 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; | 1597 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; |
1567 | saa711x_writeregs(client, saa7115_init_auto_input); | 1598 | saa711x_writeregs(sd, saa7115_init_auto_input); |
1568 | } | 1599 | } |
1569 | if (state->ident != V4L2_IDENT_SAA7111) | 1600 | if (state->ident != V4L2_IDENT_SAA7111) |
1570 | saa711x_writeregs(client, saa7115_init_misc); | 1601 | saa711x_writeregs(sd, saa7115_init_misc); |
1571 | saa711x_set_v4lstd(client, V4L2_STD_NTSC); | 1602 | saa711x_set_v4lstd(sd, V4L2_STD_NTSC); |
1572 | 1603 | ||
1573 | v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n", | 1604 | v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n", |
1574 | saa711x_read(client, R_1E_STATUS_BYTE_1_VD_DEC), saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC)); | 1605 | saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC), |
1606 | saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC)); | ||
1575 | return 0; | 1607 | return 0; |
1576 | } | 1608 | } |
1577 | 1609 | ||
1578 | /* ----------------------------------------------------------------------- */ | 1610 | /* ----------------------------------------------------------------------- */ |
1579 | 1611 | ||
1580 | static int saa7115_remove(struct i2c_client *client) | 1612 | static int saa711x_remove(struct i2c_client *client) |
1581 | { | 1613 | { |
1582 | kfree(i2c_get_clientdata(client)); | 1614 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
1615 | |||
1616 | v4l2_device_unregister_subdev(sd); | ||
1617 | kfree(to_state(sd)); | ||
1583 | return 0; | 1618 | return 0; |
1584 | } | 1619 | } |
1585 | 1620 | ||
@@ -1597,9 +1632,9 @@ MODULE_DEVICE_TABLE(i2c, saa7115_id); | |||
1597 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 1632 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
1598 | .name = "saa7115", | 1633 | .name = "saa7115", |
1599 | .driverid = I2C_DRIVERID_SAA711X, | 1634 | .driverid = I2C_DRIVERID_SAA711X, |
1600 | .command = saa7115_command, | 1635 | .command = saa711x_command, |
1601 | .probe = saa7115_probe, | 1636 | .probe = saa711x_probe, |
1602 | .remove = saa7115_remove, | 1637 | .remove = saa711x_remove, |
1603 | .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, | 1638 | .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, |
1604 | .id_table = saa7115_id, | 1639 | .id_table = saa7115_id, |
1605 | }; | 1640 | }; |