blob: fc32c3f68af1ebaae2cc03403a91ef1966ad8861 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001#include <linux/module.h>
2#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07003#include <linux/string.h>
4#include <linux/timer.h>
5#include <linux/delay.h>
6#include <linux/errno.h>
7#include <linux/slab.h>
8#include <linux/poll.h>
9#include <linux/i2c.h>
10#include <linux/types.h>
Mauro Carvalho Chehabcab462f2006-01-09 15:53:26 -020011#include <linux/videodev2.h>
12#include <media/v4l2-common.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/init.h>
14#include <linux/crc32.h>
15
Linus Torvalds1da177e2005-04-16 15:20:36 -070016
17#define MPEG_VIDEO_TARGET_BITRATE_MAX 27000
18#define MPEG_VIDEO_MAX_BITRATE_MAX 27000
19#define MPEG_TOTAL_TARGET_BITRATE_MAX 27000
20#define MPEG_PID_MAX ((1 << 14) - 1)
21
22/* Addresses to scan */
23static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END};
Linus Torvalds1da177e2005-04-16 15:20:36 -070024I2C_CLIENT_INSMOD;
25
26MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
27MODULE_AUTHOR("Andrew de Quincey");
28MODULE_LICENSE("GPL");
29
30static struct i2c_driver driver;
31static struct i2c_client client_template;
32
Frederic CAND0a4c9c92005-05-05 16:15:52 -070033enum saa6752hs_videoformat {
34 SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */
35 SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
36 SAA6752HS_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */
37 SAA6752HS_VF_SIF = 3, /* SIF video format: 352x288 */
38 SAA6752HS_VF_UNKNOWN,
39};
40
Hans Verkuil86b79d62006-06-18 16:40:10 -030041struct saa6752hs_mpeg_params {
42 /* transport streams */
43 __u16 ts_pid_pmt;
44 __u16 ts_pid_audio;
45 __u16 ts_pid_video;
46 __u16 ts_pid_pcr;
47
48 /* audio */
49 enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate;
50
51 /* video */
52 enum v4l2_mpeg_video_aspect vi_aspect;
53 enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode;
54 __u32 vi_bitrate;
55 __u32 vi_bitrate_peak;
56};
57
Frederic CAND0a4c9c92005-05-05 16:15:52 -070058static const struct v4l2_format v4l2_format_table[] =
59{
Mauro Carvalho Chehabac19ecc2005-06-23 22:05:09 -070060 [SAA6752HS_VF_D1] =
61 { .fmt = { .pix = { .width = 720, .height = 576 }}},
62 [SAA6752HS_VF_2_3_D1] =
63 { .fmt = { .pix = { .width = 480, .height = 576 }}},
64 [SAA6752HS_VF_1_2_D1] =
65 { .fmt = { .pix = { .width = 352, .height = 576 }}},
66 [SAA6752HS_VF_SIF] =
67 { .fmt = { .pix = { .width = 352, .height = 288 }}},
68 [SAA6752HS_VF_UNKNOWN] =
69 { .fmt = { .pix = { .width = 0, .height = 0}}},
Frederic CAND0a4c9c92005-05-05 16:15:52 -070070};
71
Linus Torvalds1da177e2005-04-16 15:20:36 -070072struct saa6752hs_state {
73 struct i2c_client client;
Hans Verkuil86b79d62006-06-18 16:40:10 -030074 struct saa6752hs_mpeg_params params;
Frederic CAND0a4c9c92005-05-05 16:15:52 -070075 enum saa6752hs_videoformat video_format;
Robert W. Boone9b715212005-11-08 21:36:45 -080076 v4l2_std_id standard;
Linus Torvalds1da177e2005-04-16 15:20:36 -070077};
78
79enum saa6752hs_command {
80 SAA6752HS_COMMAND_RESET = 0,
Trent Piepho657de3c2006-06-20 00:30:57 -030081 SAA6752HS_COMMAND_STOP = 1,
82 SAA6752HS_COMMAND_START = 2,
83 SAA6752HS_COMMAND_PAUSE = 3,
84 SAA6752HS_COMMAND_RECONFIGURE = 4,
85 SAA6752HS_COMMAND_SLEEP = 5,
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,
87
88 SAA6752HS_COMMAND_MAX
89};
90
91/* ---------------------------------------------------------------------- */
92
93static u8 PAT[] = {
Robert W. Boone9b715212005-11-08 21:36:45 -080094 0xc2, /* i2c register */
95 0x00, /* table number for encoder */
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Robert W. Boone9b715212005-11-08 21:36:45 -080097 0x47, /* sync */
98 0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) */
99 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
Robert W. Boone9b715212005-11-08 21:36:45 -0800101 0x00, /* PSI pointer to start of table */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
Robert W. Boone9b715212005-11-08 21:36:45 -0800103 0x00, /* tid(0) */
104 0xb0, 0x0d, /* section_syntax_indicator(1), section_length(13) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
Robert W. Boone9b715212005-11-08 21:36:45 -0800106 0x00, 0x01, /* transport_stream_id(1) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107
Robert W. Boone9b715212005-11-08 21:36:45 -0800108 0xc1, /* version_number(0), current_next_indicator(1) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
Robert W. Boone9b715212005-11-08 21:36:45 -0800110 0x00, 0x00, /* section_number(0), last_section_number(0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Robert W. Boone9b715212005-11-08 21:36:45 -0800112 0x00, 0x01, /* program_number(1) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
Robert W. Boone9b715212005-11-08 21:36:45 -0800114 0xe0, 0x00, /* PMT PID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
Robert W. Boone9b715212005-11-08 21:36:45 -0800116 0x00, 0x00, 0x00, 0x00 /* CRC32 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117};
118
119static u8 PMT[] = {
Robert W. Boone9b715212005-11-08 21:36:45 -0800120 0xc2, /* i2c register */
121 0x01, /* table number for encoder */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122
Robert W. Boone9b715212005-11-08 21:36:45 -0800123 0x47, /* sync */
124 0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid */
125 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
Robert W. Boone9b715212005-11-08 21:36:45 -0800127 0x00, /* PSI pointer to start of table */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
Robert W. Boone9b715212005-11-08 21:36:45 -0800129 0x02, /* tid(2) */
130 0xb0, 0x17, /* section_syntax_indicator(1), section_length(23) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
Robert W. Boone9b715212005-11-08 21:36:45 -0800132 0x00, 0x01, /* program_number(1) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Robert W. Boone9b715212005-11-08 21:36:45 -0800134 0xc1, /* version_number(0), current_next_indicator(1) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
Robert W. Boone9b715212005-11-08 21:36:45 -0800136 0x00, 0x00, /* section_number(0), last_section_number(0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
Robert W. Boone9b715212005-11-08 21:36:45 -0800138 0xe0, 0x00, /* PCR_PID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Robert W. Boone9b715212005-11-08 21:36:45 -0800140 0xf0, 0x00, /* program_info_length(0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
Robert W. Boone9b715212005-11-08 21:36:45 -0800142 0x02, 0xe0, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
143 0x04, 0xe0, 0x00, 0xf0, 0x00, /* audio stream type(4), pid */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
Robert W. Boone9b715212005-11-08 21:36:45 -0800145 0x00, 0x00, 0x00, 0x00 /* CRC32 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146};
147
Hans Verkuil86b79d62006-06-18 16:40:10 -0300148static struct saa6752hs_mpeg_params param_defaults =
149{
150 .ts_pid_pmt = 16,
151 .ts_pid_video = 260,
152 .ts_pid_audio = 256,
153 .ts_pid_pcr = 259,
154
155 .vi_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
156 .vi_bitrate = 4000,
157 .vi_bitrate_peak = 6000,
158 .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
159
160 .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
161};
162
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163/* ---------------------------------------------------------------------- */
164
165static int saa6752hs_chip_command(struct i2c_client* client,
166 enum saa6752hs_command command)
167{
168 unsigned char buf[3];
169 unsigned long timeout;
170 int status = 0;
171
Robert W. Boone9b715212005-11-08 21:36:45 -0800172 /* execute the command */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 switch(command) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800174 case SAA6752HS_COMMAND_RESET:
175 buf[0] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 break;
177
178 case SAA6752HS_COMMAND_STOP:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800179 buf[0] = 0x03;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 break;
181
182 case SAA6752HS_COMMAND_START:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800183 buf[0] = 0x02;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 break;
185
186 case SAA6752HS_COMMAND_PAUSE:
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800187 buf[0] = 0x04;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 break;
189
190 case SAA6752HS_COMMAND_RECONFIGURE:
191 buf[0] = 0x05;
192 break;
193
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800194 case SAA6752HS_COMMAND_SLEEP:
195 buf[0] = 0x06;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 break;
197
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800198 case SAA6752HS_COMMAND_RECONFIGURE_FORCE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 buf[0] = 0x07;
200 break;
201
202 default:
203 return -EINVAL;
204 }
205
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800206 /* set it and wait for it to be so */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 i2c_master_send(client, buf, 1);
208 timeout = jiffies + HZ * 3;
209 for (;;) {
Robert W. Boone9b715212005-11-08 21:36:45 -0800210 /* get the current status */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 buf[0] = 0x10;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800212 i2c_master_send(client, buf, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 i2c_master_recv(client, buf, 1);
214
215 if (!(buf[0] & 0x20))
216 break;
217 if (time_after(jiffies,timeout)) {
218 status = -ETIMEDOUT;
219 break;
220 }
221
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 msleep(10);
223 }
224
Robert W. Boone9b715212005-11-08 21:36:45 -0800225 /* delay a bit to let encoder settle */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 msleep(50);
227
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800228 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229}
230
231
232static int saa6752hs_set_bitrate(struct i2c_client* client,
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300233 struct saa6752hs_mpeg_params* params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800235 u8 buf[3];
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300236 int tot_bitrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237
Robert W. Boone9b715212005-11-08 21:36:45 -0800238 /* set the bitrate mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 buf[0] = 0x71;
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300240 buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 i2c_master_send(client, buf, 2);
242
Robert W. Boone9b715212005-11-08 21:36:45 -0800243 /* set the video bitrate */
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300244 if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
Robert W. Boone9b715212005-11-08 21:36:45 -0800245 /* set the target bitrate */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 buf[0] = 0x80;
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300247 buf[1] = params->vi_bitrate >> 8;
248 buf[2] = params->vi_bitrate & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 i2c_master_send(client, buf, 3);
250
Robert W. Boone9b715212005-11-08 21:36:45 -0800251 /* set the max bitrate */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 buf[0] = 0x81;
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300253 buf[1] = params->vi_bitrate_peak >> 8;
254 buf[2] = params->vi_bitrate_peak & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 i2c_master_send(client, buf, 3);
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300256 tot_bitrate = params->vi_bitrate_peak;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 } else {
Robert W. Boone9b715212005-11-08 21:36:45 -0800258 /* set the target bitrate (no max bitrate for CBR) */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800259 buf[0] = 0x81;
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300260 buf[1] = params->vi_bitrate >> 8;
261 buf[2] = params->vi_bitrate & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 i2c_master_send(client, buf, 3);
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300263 tot_bitrate = params->vi_bitrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 }
265
Robert W. Boone9b715212005-11-08 21:36:45 -0800266 /* set the audio bitrate */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800267 buf[0] = 0x94;
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300268 buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 i2c_master_send(client, buf, 2);
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300270 tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384;
271
272 /* Note: the total max bitrate is determined by adding the video and audio
273 bitrates together and also adding an extra 768kbit/s to stay on the
274 safe side. If more control should be required, then an extra MPEG control
275 should be added. */
276 tot_bitrate += 768;
277 if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX)
278 tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Robert W. Boone9b715212005-11-08 21:36:45 -0800280 /* set the total bitrate */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 buf[0] = 0xb1;
Mauro Carvalho Chehabb57e5572006-06-23 16:13:56 -0300282 buf[1] = tot_bitrate >> 8;
283 buf[2] = tot_bitrate & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 i2c_master_send(client, buf, 3);
285
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 return 0;
287}
288
Frederic CAND0a4c9c92005-05-05 16:15:52 -0700289static void saa6752hs_set_subsampling(struct i2c_client* client,
290 struct v4l2_format* f)
291{
292 struct saa6752hs_state *h = i2c_get_clientdata(client);
293 int dist_352, dist_480, dist_720;
294
295 /*
296 FIXME: translate and round width/height into EMPRESS
297 subsample type:
298
299 type | PAL | NTSC
300 ---------------------------
301 SIF | 352x288 | 352x240
302 1/2 D1 | 352x576 | 352x480
303 2/3 D1 | 480x576 | 480x480
304 D1 | 720x576 | 720x480
305 */
306
307 dist_352 = abs(f->fmt.pix.width - 352);
308 dist_480 = abs(f->fmt.pix.width - 480);
309 dist_720 = abs(f->fmt.pix.width - 720);
310 if (dist_720 < dist_480) {
311 f->fmt.pix.width = 720;
312 f->fmt.pix.height = 576;
313 h->video_format = SAA6752HS_VF_D1;
314 }
315 else if (dist_480 < dist_352) {
316 f->fmt.pix.width = 480;
317 f->fmt.pix.height = 576;
318 h->video_format = SAA6752HS_VF_2_3_D1;
319 }
320 else {
321 f->fmt.pix.width = 352;
322 if (abs(f->fmt.pix.height - 576) <
323 abs(f->fmt.pix.height - 288)) {
324 f->fmt.pix.height = 576;
325 h->video_format = SAA6752HS_VF_1_2_D1;
326 }
327 else {
328 f->fmt.pix.height = 288;
329 h->video_format = SAA6752HS_VF_SIF;
330 }
331 }
332}
333
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
Hans Verkuil86b79d62006-06-18 16:40:10 -0300335static int handle_ctrl(struct saa6752hs_mpeg_params *params,
Hans Verkuil4d6b5ae2006-06-26 09:31:18 -0300336 struct v4l2_ext_control *ctrl, unsigned int cmd)
Hans Verkuil86b79d62006-06-18 16:40:10 -0300337{
338 int old = 0, new;
Hans Verkuil4d6b5ae2006-06-26 09:31:18 -0300339 int set = (cmd == VIDIOC_S_EXT_CTRLS);
Hans Verkuil86b79d62006-06-18 16:40:10 -0300340
341 new = ctrl->value;
342 switch (ctrl->id) {
343 case V4L2_CID_MPEG_STREAM_TYPE:
344 old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
345 if (set && new != old)
346 return -ERANGE;
347 new = old;
348 break;
349 case V4L2_CID_MPEG_STREAM_PID_PMT:
350 old = params->ts_pid_pmt;
351 if (set && new > MPEG_PID_MAX)
352 return -ERANGE;
353 if (new > MPEG_PID_MAX)
354 new = MPEG_PID_MAX;
355 params->ts_pid_pmt = new;
356 break;
357 case V4L2_CID_MPEG_STREAM_PID_AUDIO:
358 old = params->ts_pid_audio;
359 if (set && new > MPEG_PID_MAX)
360 return -ERANGE;
361 if (new > MPEG_PID_MAX)
362 new = MPEG_PID_MAX;
363 params->ts_pid_audio = new;
364 break;
365 case V4L2_CID_MPEG_STREAM_PID_VIDEO:
366 old = params->ts_pid_video;
367 if (set && new > MPEG_PID_MAX)
368 return -ERANGE;
369 if (new > MPEG_PID_MAX)
370 new = MPEG_PID_MAX;
371 params->ts_pid_video = new;
372 break;
373 case V4L2_CID_MPEG_STREAM_PID_PCR:
374 old = params->ts_pid_pcr;
375 if (set && new > MPEG_PID_MAX)
376 return -ERANGE;
377 if (new > MPEG_PID_MAX)
378 new = MPEG_PID_MAX;
379 params->ts_pid_pcr = new;
380 break;
381 case V4L2_CID_MPEG_AUDIO_ENCODING:
382 old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
383 if (set && new != old)
384 return -ERANGE;
385 new = old;
386 break;
387 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
388 old = params->au_l2_bitrate;
389 if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K &&
390 new != V4L2_MPEG_AUDIO_L2_BITRATE_384K)
391 return -ERANGE;
392 if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K)
393 new = V4L2_MPEG_AUDIO_L2_BITRATE_256K;
394 else
395 new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
396 params->au_l2_bitrate = new;
397 break;
398 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
399 old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
400 if (set && new != old)
401 return -ERANGE;
402 new = old;
403 break;
404 case V4L2_CID_MPEG_VIDEO_ENCODING:
405 old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
406 if (set && new != old)
407 return -ERANGE;
408 new = old;
409 break;
410 case V4L2_CID_MPEG_VIDEO_ASPECT:
411 old = params->vi_aspect;
412 if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 &&
413 new != V4L2_MPEG_VIDEO_ASPECT_4x3)
414 return -ERANGE;
415 if (new != V4L2_MPEG_VIDEO_ASPECT_16x9)
416 new = V4L2_MPEG_VIDEO_ASPECT_4x3;
417 params->vi_aspect = new;
418 break;
419 case V4L2_CID_MPEG_VIDEO_BITRATE:
420 old = params->vi_bitrate * 1000;
421 new = 1000 * (new / 1000);
422 if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
423 return -ERANGE;
424 if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
425 new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
426 params->vi_bitrate = new / 1000;
427 break;
428 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
429 old = params->vi_bitrate_peak * 1000;
430 new = 1000 * (new / 1000);
431 if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
432 return -ERANGE;
433 if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
434 new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
435 params->vi_bitrate_peak = new / 1000;
436 break;
437 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
438 old = params->vi_bitrate_mode;
439 params->vi_bitrate_mode = new;
440 break;
441 default:
442 return -EINVAL;
443 }
444 if (cmd == VIDIOC_G_EXT_CTRLS)
445 ctrl->value = old;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 else
Hans Verkuil86b79d62006-06-18 16:40:10 -0300447 ctrl->value = new;
448 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449}
450
Hans Verkuil8b53b392008-06-27 21:18:15 -0300451static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
452 struct v4l2_queryctrl *qctrl)
453{
454 int err;
455
456 switch (qctrl->id) {
457 case V4L2_CID_MPEG_AUDIO_ENCODING:
458 return v4l2_ctrl_query_fill(qctrl,
459 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
460 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
461 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
462
463 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
464 return v4l2_ctrl_query_fill(qctrl,
465 V4L2_MPEG_AUDIO_L2_BITRATE_256K,
466 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
467 V4L2_MPEG_AUDIO_L2_BITRATE_256K);
468
469 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
470 return v4l2_ctrl_query_fill(qctrl,
471 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
472 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1,
473 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
474
475 case V4L2_CID_MPEG_VIDEO_ENCODING:
476 return v4l2_ctrl_query_fill(qctrl,
477 V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
478 V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
479 V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
480
481 case V4L2_CID_MPEG_VIDEO_ASPECT:
482 return v4l2_ctrl_query_fill(qctrl,
483 V4L2_MPEG_VIDEO_ASPECT_4x3,
484 V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
485 V4L2_MPEG_VIDEO_ASPECT_4x3);
486
487 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
488 err = v4l2_ctrl_query_fill_std(qctrl);
489 if (err == 0 &&
490 params->vi_bitrate_mode ==
491 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
492 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
493 return err;
494
495 case V4L2_CID_MPEG_STREAM_TYPE:
496 return v4l2_ctrl_query_fill(qctrl,
497 V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
498 V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1,
499 V4L2_MPEG_STREAM_TYPE_MPEG2_TS);
500
501 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
502 case V4L2_CID_MPEG_VIDEO_BITRATE:
503 case V4L2_CID_MPEG_STREAM_PID_PMT:
504 case V4L2_CID_MPEG_STREAM_PID_AUDIO:
505 case V4L2_CID_MPEG_STREAM_PID_VIDEO:
506 case V4L2_CID_MPEG_STREAM_PID_PCR:
507 return v4l2_ctrl_query_fill_std(qctrl);
508
509 default:
510 break;
511 }
512 return -EINVAL;
513}
514
515static int saa6752hs_qmenu(struct saa6752hs_mpeg_params *params,
516 struct v4l2_querymenu *qmenu)
517{
518 static const char *mpeg_audio_l2_bitrate[] = {
519 "",
520 "",
521 "",
522 "",
523 "",
524 "",
525 "",
526 "",
527 "",
528 "",
529 "",
530 "256 kbps",
531 "",
532 "384 kbps",
533 NULL
534 };
535 struct v4l2_queryctrl qctrl;
536 int err;
537
538 qctrl.id = qmenu->id;
539 err = saa6752hs_qctrl(params, &qctrl);
540 if (err)
541 return err;
542 if (qmenu->id == V4L2_CID_MPEG_AUDIO_L2_BITRATE)
543 return v4l2_ctrl_query_menu(qmenu, &qctrl,
544 mpeg_audio_l2_bitrate);
545 return v4l2_ctrl_query_menu(qmenu, &qctrl,
546 v4l2_ctrl_get_menu(qmenu->id));
547}
548
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549static int saa6752hs_init(struct i2c_client* client)
550{
551 unsigned char buf[9], buf2[4];
552 struct saa6752hs_state *h;
553 u32 crc;
554 unsigned char localPAT[256];
555 unsigned char localPMT[256];
556
557 h = i2c_get_clientdata(client);
558
Robert W. Boone9b715212005-11-08 21:36:45 -0800559 /* Set video format - must be done first as it resets other settings */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 buf[0] = 0x41;
Frederic CAND0a4c9c92005-05-05 16:15:52 -0700561 buf[1] = h->video_format;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 i2c_master_send(client, buf, 2);
563
Robert W. Boone9b715212005-11-08 21:36:45 -0800564 /* Set number of lines in input signal */
565 buf[0] = 0x40;
566 buf[1] = 0x00;
567 if (h->standard & V4L2_STD_525_60)
568 buf[1] = 0x01;
569 i2c_master_send(client, buf, 2);
570
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800571 /* set bitrate */
572 saa6752hs_set_bitrate(client, &h->params);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573
Robert W. Boone9b715212005-11-08 21:36:45 -0800574 /* Set GOP structure {3, 13} */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 buf[0] = 0x72;
576 buf[1] = 0x03;
577 buf[2] = 0x0D;
578 i2c_master_send(client,buf,3);
579
Trent Piepho657de3c2006-06-20 00:30:57 -0300580 /* Set minimum Q-scale {4} */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 buf[0] = 0x82;
582 buf[1] = 0x04;
583 i2c_master_send(client,buf,2);
584
Trent Piepho657de3c2006-06-20 00:30:57 -0300585 /* Set maximum Q-scale {12} */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 buf[0] = 0x83;
587 buf[1] = 0x0C;
588 i2c_master_send(client,buf,2);
589
Trent Piepho657de3c2006-06-20 00:30:57 -0300590 /* Set Output Protocol */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 buf[0] = 0xD0;
592 buf[1] = 0x81;
593 i2c_master_send(client,buf,2);
594
Trent Piepho657de3c2006-06-20 00:30:57 -0300595 /* Set video output stream format {TS} */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 buf[0] = 0xB0;
597 buf[1] = 0x05;
598 i2c_master_send(client,buf,2);
599
600 /* compute PAT */
601 memcpy(localPAT, PAT, sizeof(PAT));
602 localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
603 localPAT[18] = h->params.ts_pid_pmt & 0xff;
604 crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);
605 localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
606 localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
607 localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
608 localPAT[sizeof(PAT) - 1] = crc & 0xFF;
609
610 /* compute PMT */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800611 memcpy(localPMT, PMT, sizeof(PMT));
612 localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
613 localPMT[4] = h->params.ts_pid_pmt & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);
615 localPMT[16] = h->params.ts_pid_pcr & 0xFF;
616 localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F);
617 localPMT[21] = h->params.ts_pid_video & 0xFF;
618 localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);
619 localPMT[26] = h->params.ts_pid_audio & 0xFF;
620 crc = crc32_be(~0, &localPMT[7], sizeof(PMT) - 7 - 4);
621 localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF;
622 localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF;
623 localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
624 localPMT[sizeof(PMT) - 1] = crc & 0xFF;
625
Trent Piepho657de3c2006-06-20 00:30:57 -0300626 /* Set Audio PID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 buf[0] = 0xC1;
628 buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF;
629 buf[2] = h->params.ts_pid_audio & 0xFF;
630 i2c_master_send(client,buf,3);
631
Robert W. Boone9b715212005-11-08 21:36:45 -0800632 /* Set Video PID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 buf[0] = 0xC0;
634 buf[1] = (h->params.ts_pid_video >> 8) & 0xFF;
635 buf[2] = h->params.ts_pid_video & 0xFF;
636 i2c_master_send(client,buf,3);
637
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800638 /* Set PCR PID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 buf[0] = 0xC4;
640 buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF;
641 buf[2] = h->params.ts_pid_pcr & 0xFF;
642 i2c_master_send(client,buf,3);
643
Robert W. Boone9b715212005-11-08 21:36:45 -0800644 /* Send SI tables */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 i2c_master_send(client,localPAT,sizeof(PAT));
646 i2c_master_send(client,localPMT,sizeof(PMT));
647
Robert W. Boone9b715212005-11-08 21:36:45 -0800648 /* mute then unmute audio. This removes buzzing artefacts */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 buf[0] = 0xa4;
650 buf[1] = 1;
651 i2c_master_send(client, buf, 2);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800652 buf[1] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 i2c_master_send(client, buf, 2);
654
Robert W. Boone9b715212005-11-08 21:36:45 -0800655 /* start it going */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
657
Robert W. Boone9b715212005-11-08 21:36:45 -0800658 /* readout current state */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 buf[0] = 0xE1;
660 buf[1] = 0xA7;
661 buf[2] = 0xFE;
662 buf[3] = 0x82;
663 buf[4] = 0xB0;
664 i2c_master_send(client, buf, 5);
665 i2c_master_recv(client, buf2, 4);
666
Robert W. Boone9b715212005-11-08 21:36:45 -0800667 /* change aspect ratio */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 buf[0] = 0xE0;
669 buf[1] = 0xA7;
670 buf[2] = 0xFE;
671 buf[3] = 0x82;
672 buf[4] = 0xB0;
673 buf[5] = buf2[0];
Hans Verkuil86b79d62006-06-18 16:40:10 -0300674 switch(h->params.vi_aspect) {
675 case V4L2_MPEG_VIDEO_ASPECT_16x9:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 buf[6] = buf2[1] | 0x40;
677 break;
Hans Verkuil86b79d62006-06-18 16:40:10 -0300678 case V4L2_MPEG_VIDEO_ASPECT_4x3:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 default:
680 buf[6] = buf2[1] & 0xBF;
681 break;
682 break;
683 }
684 buf[7] = buf2[2];
685 buf[8] = buf2[3];
686 i2c_master_send(client, buf, 9);
687
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 return 0;
689}
690
691static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
692{
693 struct saa6752hs_state *h;
694
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
Panagiotis Issaris74081872006-01-11 19:40:56 -0200696 if (NULL == (h = kzalloc(sizeof(*h), GFP_KERNEL)))
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800697 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 h->client = client_template;
699 h->params = param_defaults;
700 h->client.adapter = adap;
701 h->client.addr = addr;
702
Robert W. Boone9b715212005-11-08 21:36:45 -0800703 /* Assume 625 input lines */
704 h->standard = 0;
705
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 i2c_set_clientdata(&h->client, h);
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800707 i2c_attach_client(&h->client);
Mauro Carvalho Chehab674434c2005-12-12 00:37:28 -0800708
Mauro Carvalho Chehabcab462f2006-01-09 15:53:26 -0200709 v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1);
710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 return 0;
712}
713
714static int saa6752hs_probe(struct i2c_adapter *adap)
715{
716 if (adap->class & I2C_CLASS_TV_ANALOG)
717 return i2c_probe(adap, &addr_data, saa6752hs_attach);
718 return 0;
719}
720
721static int saa6752hs_detach(struct i2c_client *client)
722{
723 struct saa6752hs_state *h;
724
725 h = i2c_get_clientdata(client);
726 i2c_detach_client(client);
727 kfree(h);
728 return 0;
729}
730
731static int
732saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
733{
734 struct saa6752hs_state *h = i2c_get_clientdata(client);
Hans Verkuil86b79d62006-06-18 16:40:10 -0300735 struct v4l2_ext_controls *ctrls = arg;
Hans Verkuil86b79d62006-06-18 16:40:10 -0300736 struct saa6752hs_mpeg_params params;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 int err = 0;
Hans Verkuil86b79d62006-06-18 16:40:10 -0300738 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800740 switch (cmd) {
Hans Verkuil86b79d62006-06-18 16:40:10 -0300741 case VIDIOC_S_EXT_CTRLS:
742 if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
743 return -EINVAL;
744 if (ctrls->count == 0) {
745 /* apply settings and start encoder */
746 saa6752hs_init(client);
747 break;
748 }
749 /* fall through */
750 case VIDIOC_TRY_EXT_CTRLS:
751 case VIDIOC_G_EXT_CTRLS:
752 if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
753 return -EINVAL;
754 params = h->params;
755 for (i = 0; i < ctrls->count; i++) {
756 if ((err = handle_ctrl(&params, ctrls->controls + i, cmd))) {
757 ctrls->error_idx = i;
758 return err;
759 }
760 }
761 h->params = params;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 break;
Hans Verkuil8b53b392008-06-27 21:18:15 -0300763 case VIDIOC_QUERYCTRL:
764 return saa6752hs_qctrl(&h->params, arg);
765 case VIDIOC_QUERYMENU:
766 return saa6752hs_qmenu(&h->params, arg);
Frederic CAND0a4c9c92005-05-05 16:15:52 -0700767 case VIDIOC_G_FMT:
768 {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800769 struct v4l2_format *f = arg;
Frederic CAND0a4c9c92005-05-05 16:15:52 -0700770
771 if (h->video_format == SAA6752HS_VF_UNKNOWN)
772 h->video_format = SAA6752HS_VF_D1;
773 f->fmt.pix.width =
774 v4l2_format_table[h->video_format].fmt.pix.width;
775 f->fmt.pix.height =
776 v4l2_format_table[h->video_format].fmt.pix.height;
777 break ;
778 }
779 case VIDIOC_S_FMT:
780 {
781 struct v4l2_format *f = arg;
782
783 saa6752hs_set_subsampling(client, f);
784 break;
785 }
Robert W. Boone9b715212005-11-08 21:36:45 -0800786 case VIDIOC_S_STD:
787 h->standard = *((v4l2_std_id *) arg);
788 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 default:
790 /* nothing */
791 break;
792 }
793
794 return err;
795}
796
797/* ----------------------------------------------------------------------- */
798
799static struct i2c_driver driver = {
Laurent Riffard604f28e2005-11-26 20:43:39 +0100800 .driver = {
Mauro Carvalho Chehabcab462f2006-01-09 15:53:26 -0200801 .name = "saa6752hs",
Laurent Riffard604f28e2005-11-26 20:43:39 +0100802 },
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800803 .id = I2C_DRIVERID_SAA6752HS,
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800804 .attach_adapter = saa6752hs_probe,
805 .detach_client = saa6752hs_detach,
806 .command = saa6752hs_command,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807};
808
809static struct i2c_client client_template =
810{
Jean Delvarefae91e72005-08-15 19:57:04 +0200811 .name = "saa6752hs",
Mauro Carvalho Chehabafd1a0c2005-12-12 00:37:27 -0800812 .driver = &driver,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813};
814
815static int __init saa6752hs_init_module(void)
816{
817 return i2c_add_driver(&driver);
818}
819
820static void __exit saa6752hs_cleanup_module(void)
821{
822 i2c_del_driver(&driver);
823}
824
825module_init(saa6752hs_init_module);
826module_exit(saa6752hs_cleanup_module);
827
828/*
829 * Overrides for Emacs so that we follow Linus's tabbing style.
830 * ---------------------------------------------------------------------------
831 * Local variables:
832 * c-basic-offset: 8
833 * End:
834 */