aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2006-08-29 21:07:03 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-09-26 11:30:34 -0400
commit89f75ffc7e97d96ea76556671446d57d77c46beb (patch)
tree1252810a156b30b1bf1c2a36fc91f90d1f75c25e
parent96ecfc4edf6bdb535b4ae3d87db2ba7f91596dd8 (diff)
V4L/DVB (4553): Add support for saa7111 and partial support for saa7118
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/video/saa7115.c252
-rw-r--r--include/media/v4l2-common.h9
2 files changed, 195 insertions, 66 deletions
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index d5052dbd0744..900c65772fa0 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -1,4 +1,6 @@
1/* saa7115 - Philips SAA7113/SAA7114/SAA7115 video decoder driver 1/* saa711x - Philips SAA711x video decoder driver
2 * This driver can work with saa7111, saa7111a, saa7113, saa7114,
3 * saa7115 and saa7118.
2 * 4 *
3 * Based on saa7114 driver by Maxim Yevtyushkin, which is based on 5 * Based on saa7114 driver by Maxim Yevtyushkin, which is based on
4 * the saa7111 driver by Dave Perks. 6 * the saa7111 driver by Dave Perks.
@@ -16,7 +18,9 @@
16 * (2/17/2003) 18 * (2/17/2003)
17 * 19 *
18 * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl> 20 * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl>
19 * SAA7113 support by Mauro Carvalho Chehab <mchehab@infradead.org> 21 *
22 * Copyright (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
23 * SAA7111, SAA7113 and SAA7118 support
20 * 24 *
21 * This program is free software; you can redistribute it and/or 25 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License 26 * modify it under the terms of the GNU General Public License
@@ -44,7 +48,7 @@
44#include <media/saa7115.h> 48#include <media/saa7115.h>
45#include <asm/div64.h> 49#include <asm/div64.h>
46 50
47MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver"); 51MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
48MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, " 52MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
49 "Hans Verkuil, Mauro Carvalho Chehab"); 53 "Hans Verkuil, Mauro Carvalho Chehab");
50MODULE_LICENSE("GPL"); 54MODULE_LICENSE("GPL");
@@ -55,8 +59,8 @@ module_param(debug, bool, 0644);
55MODULE_PARM_DESC(debug, "Debug level (0-1)"); 59MODULE_PARM_DESC(debug, "Debug level (0-1)");
56 60
57static unsigned short normal_i2c[] = { 61static unsigned short normal_i2c[] = {
58 0x4a >> 1, 0x48 >> 1, /* SAA7113 */ 62 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
59 0x42 >> 1, 0x40 >> 1, /* SAA7114 and SAA7115 */ 63 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
60 I2C_CLIENT_END }; 64 I2C_CLIENT_END };
61 65
62 66
@@ -86,15 +90,58 @@ static inline int saa7115_write(struct i2c_client *client, u8 reg, u8 value)
86 return i2c_smbus_write_byte_data(client, reg, value); 90 return i2c_smbus_write_byte_data(client, reg, value);
87} 91}
88 92
93/* Sanity routine to check if a register is present */
94static int saa711x_has_reg(const int id, const u8 reg)
95{
96 switch (id) {
97 case V4L2_IDENT_SAA7111:
98 if (reg>0x1f || reg==1 || reg==0x0f || reg==0x14 || reg==0x18
99 || reg==0x19 || reg==0x1d || reg==0x1e)
100 return 0;
101 case V4L2_IDENT_SAA7113:
102 if (reg>0x62 || reg==0x14 || (reg>=0x18 && reg<=0x1e) ||
103 (reg>=0x20 && reg<=0x3f) ||reg==0x5f )
104 return 0;
105 case V4L2_IDENT_SAA7114:
106 if (reg>=0xf0 || (reg>=0x1a && reg<=0x1e) ||
107 (reg>=0x20 && reg<=0x2f) ||
108 (reg>=0x63 && reg<=0x7f) )
109 return 0;
110 case V4L2_IDENT_SAA7115:
111 if ((reg>=0x20 && reg<=0x2f) || (reg==0x5c) ||
112 (reg>=0xfc && reg<=0xfe) )
113 return 0;
114 case V4L2_IDENT_SAA7118:
115 if (reg>=0xf0 || (reg>=0x1a && reg<=0x1d) ||
116 (reg>=0x63 && reg<=0x6f) )
117 return 0;
118 }
119
120 /* Those registers are reserved for all family */
121 if (unlikely((reg>=0x20 && reg<=0x22) ||
122 (reg>=0x26 && reg<=0x28) ||
123 (reg>=0x3b && reg<=0x3f) || (reg==0x5f) ||
124 (reg>=0x63 && reg<=0x6f) ) )
125 return 0;
126
127 return 1;
128}
129
89static int saa7115_writeregs(struct i2c_client *client, const unsigned char *regs) 130static int saa7115_writeregs(struct i2c_client *client, const unsigned char *regs)
90{ 131{
132 struct saa7115_state *state = i2c_get_clientdata(client);
91 unsigned char reg, data; 133 unsigned char reg, data;
92 134
93 while (*regs != 0x00) { 135 while (*regs != 0x00) {
94 reg = *(regs++); 136 reg = *(regs++);
95 data = *(regs++); 137 data = *(regs++);
96 if (saa7115_write(client, reg, data) < 0) 138
97 return -1; 139 /* According with datasheets, reserved regs should be
140 filled with 0 - seems better not to touch on they */
141 if (saa711x_has_reg(state->ident,reg)) {
142 if (saa7115_write(client, reg, data) < 0)
143 return -1;
144 }
98 } 145 }
99 return 0; 146 return 0;
100} 147}
@@ -106,10 +153,80 @@ static inline int saa7115_read(struct i2c_client *client, u8 reg)
106 153
107/* ----------------------------------------------------------------------- */ 154/* ----------------------------------------------------------------------- */
108 155
156/* SAA7111 initialization table */
157static const unsigned char saa7111_init_auto_input[] = {
158 R_01_INC_DELAY, 0x00, /* reserved */
159
160 /*front end */
161 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
162 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
163 * GAFIX=0, GAI1=256, GAI2=256 */
164 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
165 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
166
167 /* decoder */
168 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
169 * pixels after end of last line */
170 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
171 * work with NTSC, too */
172 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
173 * VTRC=1, HPLL=0, VNOI=0 */
174 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
175 * VBLB=0, UPTCV=0, APER=1 */
176 R_0A_LUMA_BRIGHT_CNTL, 0x80,
177 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
178 R_0C_CHROMA_SAT_CNTL, 0x40,
179 R_0D_CHROMA_HUE_CNTL, 0x00,
180 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
181 * FCTC=0, CHBW=1 */
182 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
183 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
184 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
185 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
186 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
187 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
188 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
189 R_15_VGATE_START_FID_CHG, 0x00,
190 R_16_VGATE_STOP, 0x00,
191 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
192
193 0x00, 0x00
194};
195
196/* SAA7113 init codes */
197static const unsigned char saa7113_init_auto_input[] = {
198 R_01_INC_DELAY, 0x08,
199 R_02_INPUT_CNTL_1, 0xc2,
200 R_03_INPUT_CNTL_2, 0x30,
201 R_04_INPUT_CNTL_3, 0x00,
202 R_05_INPUT_CNTL_4, 0x00,
203 R_06_H_SYNC_START, 0x89,
204 R_07_H_SYNC_STOP, 0x0d,
205 R_08_SYNC_CNTL, 0x88,
206 R_09_LUMA_CNTL, 0x01,
207 R_0A_LUMA_BRIGHT_CNTL, 0x80,
208 R_0B_LUMA_CONTRAST_CNTL, 0x47,
209 R_0C_CHROMA_SAT_CNTL, 0x40,
210 R_0D_CHROMA_HUE_CNTL, 0x00,
211 R_0E_CHROMA_CNTL_1, 0x01,
212 R_0F_CHROMA_GAIN_CNTL, 0x2a,
213 R_10_CHROMA_CNTL_2, 0x08,
214 R_11_MODE_DELAY_CNTL, 0x0c,
215 R_12_RT_SIGNAL_CNTL, 0x07,
216 R_13_RT_X_PORT_OUT_CNTL, 0x00,
217 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
218 R_15_VGATE_START_FID_CHG, 0x00,
219 R_16_VGATE_STOP, 0x00,
220 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
221
222 0x00, 0x00
223};
224
109/* If a value differs from the Hauppauge driver values, then the comment starts with 225/* If a value differs from the Hauppauge driver values, then the comment starts with
110 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the 226 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
111 Hauppauge driver sets. */ 227 Hauppauge driver sets. */
112 228
229/* SAA7114 and SAA7115 initialization table */
113static const unsigned char saa7115_init_auto_input[] = { 230static const unsigned char saa7115_init_auto_input[] = {
114 /* Front-End Part */ 231 /* Front-End Part */
115 R_01_INC_DELAY, 0x48, /* white peak control disabled */ 232 R_01_INC_DELAY, 0x48, /* white peak control disabled */
@@ -142,6 +259,7 @@ static const unsigned char saa7115_init_auto_input[] = {
142 0x00, 0x00 259 0x00, 0x00
143}; 260};
144 261
262/* Used to reset saa7113, saa7114 and saa7115 */
145static const unsigned char saa7115_cfg_reset_scaler[] = { 263static const unsigned char saa7115_cfg_reset_scaler[] = {
146 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */ 264 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
147 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */ 265 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
@@ -152,6 +270,7 @@ static const unsigned char saa7115_cfg_reset_scaler[] = {
152 270
153/* ============== SAA7715 VIDEO templates ============= */ 271/* ============== SAA7715 VIDEO templates ============= */
154 272
273/* Used on saa7114 and saa7115 */
155static const unsigned char saa7115_cfg_60hz_fullres_x[] = { 274static const unsigned char saa7115_cfg_60hz_fullres_x[] = {
156 /* hsize = 0x2d0 = 720 */ 275 /* hsize = 0x2d0 = 720 */
157 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0, 276 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
@@ -170,6 +289,7 @@ static const unsigned char saa7115_cfg_60hz_fullres_x[] = {
170 0x00, 0x00 289 0x00, 0x00
171}; 290};
172 291
292/* Used on saa7114 and saa7115 */
173static const unsigned char saa7115_cfg_60hz_fullres_y[] = { 293static const unsigned char saa7115_cfg_60hz_fullres_y[] = {
174 /* output window size = 248 (but 60hz is 240?) */ 294 /* output window size = 248 (but 60hz is 240?) */
175 R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, 0xf8, 295 R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, 0xf8,
@@ -408,33 +528,6 @@ static const unsigned char saa7115_cfg_vbi_off[] = {
408 0x00, 0x00 528 0x00, 0x00
409}; 529};
410 530
411static const unsigned char saa7113_init_auto_input[] = {
412 R_01_INC_DELAY, 0x08,
413 R_02_INPUT_CNTL_1, 0xc2,
414 R_03_INPUT_CNTL_2, 0x30,
415 R_04_INPUT_CNTL_3, 0x00,
416 R_05_INPUT_CNTL_4, 0x00,
417 R_06_H_SYNC_START, 0x89,
418 R_07_H_SYNC_STOP, 0x0d,
419 R_08_SYNC_CNTL, 0x88,
420 R_09_LUMA_CNTL, 0x01,
421 R_0A_LUMA_BRIGHT_CNTL, 0x80,
422 R_0B_LUMA_CONTRAST_CNTL, 0x47,
423 R_0C_CHROMA_SAT_CNTL, 0x40,
424 R_0D_CHROMA_HUE_CNTL, 0x00,
425 R_0E_CHROMA_CNTL_1, 0x01,
426 R_0F_CHROMA_GAIN_CNTL, 0x2a,
427 R_10_CHROMA_CNTL_2, 0x08,
428 R_11_MODE_DELAY_CNTL, 0x0c,
429 R_12_RT_SIGNAL_CNTL, 0x07,
430 R_13_RT_X_PORT_OUT_CNTL, 0x00,
431 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
432 R_15_VGATE_START_FID_CHG, 0x00,
433 R_16_VGATE_STOP, 0x00,
434 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
435
436 0x00, 0x00
437};
438 531
439static const unsigned char saa7115_init_misc[] = { 532static const unsigned char saa7115_init_misc[] = {
440 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01, 533 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
@@ -662,7 +755,6 @@ static int saa7115_decode_wss(u8 * p)
662 return wss; 755 return wss;
663} 756}
664 757
665
666static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq) 758static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
667{ 759{
668 struct saa7115_state *state = i2c_get_clientdata(client); 760 struct saa7115_state *state = i2c_get_clientdata(client);
@@ -672,16 +764,16 @@ static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
672 u64 f; 764 u64 f;
673 u8 acc = 0; /* reg 0x3a, audio clock control */ 765 u8 acc = 0; /* reg 0x3a, audio clock control */
674 766
767 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
768 if (!saa711x_has_reg(state->ident,R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
769 return 0;
770
675 v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq); 771 v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
676 772
677 /* sanity check */ 773 /* sanity check */
678 if (freq < 32000 || freq > 48000) 774 if (freq < 32000 || freq > 48000)
679 return -EINVAL; 775 return -EINVAL;
680 776
681 /* The saa7113 has no audio clock */
682 if (state->ident == V4L2_IDENT_SAA7113)
683 return 0;
684
685 /* hz is the refresh rate times 100 */ 777 /* hz is the refresh rate times 100 */
686 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000; 778 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
687 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */ 779 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
@@ -799,7 +891,6 @@ static int saa7115_get_v4lctrl(struct i2c_client *client, struct v4l2_control *c
799static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) 891static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
800{ 892{
801 struct saa7115_state *state = i2c_get_clientdata(client); 893 struct saa7115_state *state = i2c_get_clientdata(client);
802 int taskb = saa7115_read(client, R_80_GLOBAL_CNTL_1) & 0x10;
803 894
804 /* Prevent unnecessary standard changes. During a standard 895 /* Prevent unnecessary standard changes. During a standard
805 change the I-Port is temporarily disabled. Any devices 896 change the I-Port is temporarily disabled. Any devices
@@ -821,7 +912,7 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
821 } 912 }
822 913
823 /* Register 0E - Bits D6-D4 on NO-AUTO mode 914 /* Register 0E - Bits D6-D4 on NO-AUTO mode
824 (SAA7113 doesn't have auto mode) 915 (SAA7111 and SAA7113 doesn't have auto mode)
825 50 Hz / 625 lines 60 Hz / 525 lines 916 50 Hz / 625 lines 60 Hz / 525 lines
826 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz) 917 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
827 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz) 918 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
@@ -829,7 +920,8 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
829 011 NTSC N (3.58MHz) PAL M (3.58MHz) 920 011 NTSC N (3.58MHz) PAL M (3.58MHz)
830 100 reserved NTSC-Japan (3.58MHz) 921 100 reserved NTSC-Japan (3.58MHz)
831 */ 922 */
832 if (state->ident == V4L2_IDENT_SAA7113) { 923 if (state->ident == V4L2_IDENT_SAA7111 ||
924 state->ident == V4L2_IDENT_SAA7113) {
833 u8 reg = saa7115_read(client, R_0E_CHROMA_CNTL_1) & 0x8f; 925 u8 reg = saa7115_read(client, R_0E_CHROMA_CNTL_1) & 0x8f;
834 926
835 if (std == V4L2_STD_PAL_M) { 927 if (std == V4L2_STD_PAL_M) {
@@ -842,18 +934,19 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
842 reg |= 0x40; 934 reg |= 0x40;
843 } 935 }
844 saa7115_write(client, R_0E_CHROMA_CNTL_1, reg); 936 saa7115_write(client, R_0E_CHROMA_CNTL_1, reg);
845 } 937 } else {
846 938 /* restart task B if needed */
939 int taskb = saa7115_read(client, R_80_GLOBAL_CNTL_1) & 0x10;
847 940
848 state->std = std; 941 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
942 saa7115_writeregs(client, saa7115_cfg_vbi_on);
943 }
849 944
850 /* restart task B if needed */ 945 /* switch audio mode too! */
851 if (taskb && state->ident != V4L2_IDENT_SAA7115) { 946 saa7115_set_audio_clock_freq(client, state->audclk_freq);
852 saa7115_writeregs(client, saa7115_cfg_vbi_on);
853 } 947 }
854 948
855 /* switch audio mode too! */ 949 state->std = std;
856 saa7115_set_audio_clock_freq(client, state->audclk_freq);
857} 950}
858 951
859static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client) 952static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client)
@@ -919,9 +1012,16 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
919 u8 lcr[24]; 1012 u8 lcr[24];
920 int i, x; 1013 int i, x;
921 1014
922 /* saa7113/7114 doesn't yet support VBI */ 1015#if 1
1016 /* saa7113/7114/7118 VBI support are experimental */
1017 if (!saa711x_has_reg(state->ident,R_41_LCR_BASE))
1018 return;
1019
1020#else
1021 /* SAA7113 and SAA7118 also should support VBI - Need testing */
923 if (state->ident != V4L2_IDENT_SAA7115) 1022 if (state->ident != V4L2_IDENT_SAA7115)
924 return; 1023 return;
1024#endif
925 1025
926 for (i = 0; i <= 23; i++) 1026 for (i = 0; i <= 23; i++)
927 lcr[i] = 0xff; 1027 lcr[i] = 0xff;
@@ -1021,8 +1121,9 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
1021 struct saa7115_state *state = i2c_get_clientdata(client); 1121 struct saa7115_state *state = i2c_get_clientdata(client);
1022 struct v4l2_pix_format *pix; 1122 struct v4l2_pix_format *pix;
1023 int HPSC, HFSC; 1123 int HPSC, HFSC;
1024 int VSCY, Vsrc; 1124 int VSCY;
1025 int is_50hz = state->std & V4L2_STD_625_50; 1125 int is_50hz = state->std & V4L2_STD_625_50;
1126 int Vsrc = is_50hz ? 576 : 480;
1026 1127
1027 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { 1128 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
1028 saa7115_set_lcr(client, &fmt->fmt.sliced); 1129 saa7115_set_lcr(client, &fmt->fmt.sliced);
@@ -1041,18 +1142,29 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
1041 if ((pix->height < 1) || (pix->height > 960)) 1142 if ((pix->height < 1) || (pix->height > 960))
1042 return -EINVAL; 1143 return -EINVAL;
1043 1144
1145 if (!saa711x_has_reg(state->ident,R_D0_B_HORIZ_PRESCALING)) {
1146 /* Decoder only supports 720 columns and 480 or 576 lines */
1147 if (pix->width != 720)
1148 return -EINVAL;
1149 if (pix->height != Vsrc)
1150 return -EINVAL;
1151 }
1152
1044 /* probably have a valid size, let's set it */ 1153 /* probably have a valid size, let's set it */
1045 /* Set output width/height */ 1154 /* Set output width/height */
1046 /* width */ 1155 /* width */
1047 saa7115_write(client, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 1156
1048 (u8) (pix->width & 0xff)); 1157 if (!saa711x_has_reg(state->ident,R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH)) {
1049 saa7115_write(client, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 1158 saa7115_write(client, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
1050 (u8) ((pix->width >> 8) & 0xff)); 1159 (u8) (pix->width & 0xff));
1051 /* height */ 1160 saa7115_write(client, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
1052 saa7115_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH, 1161 (u8) ((pix->width >> 8) & 0xff));
1053 (u8) (pix->height & 0xff)); 1162 /* height */
1054 saa7115_write(client, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB, 1163 saa7115_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
1055 (u8) ((pix->height >> 8) & 0xff)); 1164 (u8) (pix->height & 0xff));
1165 saa7115_write(client, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
1166 (u8) ((pix->height >> 8) & 0xff));
1167 }
1056 1168
1057 /* Scaling settings */ 1169 /* Scaling settings */
1058 /* Hprescaler is floor(inres/outres) */ 1170 /* Hprescaler is floor(inres/outres) */
@@ -1090,8 +1202,6 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
1090 } 1202 }
1091 } 1203 }
1092 1204
1093 Vsrc = is_50hz ? 576 : 480;
1094
1095 if (pix->height != Vsrc) { 1205 if (pix->height != Vsrc) {
1096 VSCY = (int)((1024 * Vsrc) / pix->height); 1206 VSCY = (int)((1024 * Vsrc) / pix->height);
1097 v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); 1207 v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
@@ -1123,6 +1233,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
1123 } 1233 }
1124 1234
1125 saa7115_writeregs(client, saa7115_cfg_reset_scaler); 1235 saa7115_writeregs(client, saa7115_cfg_reset_scaler);
1236
1126 return 0; 1237 return 0;
1127} 1238}
1128 1239
@@ -1468,15 +1579,25 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
1468 state->hue = 0; 1579 state->hue = 0;
1469 state->sat = 64; 1580 state->sat = 64;
1470 switch (chip_id) { 1581 switch (chip_id) {
1582 case 1:
1583 state->ident = V4L2_IDENT_SAA7111;
1584 break;
1471 case 3: 1585 case 3:
1472 state->ident = V4L2_IDENT_SAA7113; 1586 state->ident = V4L2_IDENT_SAA7113;
1473 break; 1587 break;
1474 case 4: 1588 case 4:
1475 state->ident = V4L2_IDENT_SAA7114; 1589 state->ident = V4L2_IDENT_SAA7114;
1476 break; 1590 break;
1477 default: 1591 case 5:
1478 state->ident = V4L2_IDENT_SAA7115; 1592 state->ident = V4L2_IDENT_SAA7115;
1479 break; 1593 break;
1594 case 8:
1595 state->ident = V4L2_IDENT_SAA7118;
1596 break;
1597 default:
1598 state->ident = V4L2_IDENT_SAA7111;
1599 v4l_info(client, "WARNING: Chip is not known - Falling back to saa7111\n");
1600
1480 } 1601 }
1481 1602
1482 state->audclk_freq = 48000; 1603 state->audclk_freq = 48000;
@@ -1484,7 +1605,8 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
1484 v4l_dbg(1, debug, client, "writing init values\n"); 1605 v4l_dbg(1, debug, client, "writing init values\n");
1485 1606
1486 /* init to 60hz/48khz */ 1607 /* init to 60hz/48khz */
1487 if (state->ident == V4L2_IDENT_SAA7113) { 1608 if (state->ident == V4L2_IDENT_SAA7111 ||
1609 state->ident == V4L2_IDENT_SAA7113) {
1488 state->crystal_freq = SAA7115_FREQ_24_576_MHZ; 1610 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1489 saa7115_writeregs(client, saa7113_init_auto_input); 1611 saa7115_writeregs(client, saa7113_init_auto_input);
1490 } else { 1612 } else {
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 8721ac4a45a7..ce24a6ad445c 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -121,10 +121,17 @@ enum v4l2_chip_ident {
121 /* general idents: reserved range 0-49 */ 121 /* general idents: reserved range 0-49 */
122 V4L2_IDENT_UNKNOWN = 0, 122 V4L2_IDENT_UNKNOWN = 0,
123 123
124 /* module saa7115: reserved range 100-149 */ 124 /* module saa7110: just ident= 100 */
125 V4L2_IDENT_SAA7110 = 100,
126
127 /* module saa7111: just ident= 101 */
128 V4L2_IDENT_SAA7111 = 101,
129
130 /* module saa7115: reserved range 102-149 */
125 V4L2_IDENT_SAA7113 = 103, 131 V4L2_IDENT_SAA7113 = 103,
126 V4L2_IDENT_SAA7114 = 104, 132 V4L2_IDENT_SAA7114 = 104,
127 V4L2_IDENT_SAA7115 = 105, 133 V4L2_IDENT_SAA7115 = 105,
134 V4L2_IDENT_SAA7118 = 108,
128 135
129 /* module saa7127: reserved range 150-199 */ 136 /* module saa7127: reserved range 150-199 */
130 V4L2_IDENT_SAA7127 = 157, 137 V4L2_IDENT_SAA7127 = 157,