saa6752hs.c 15.7 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/i2c.h>
#include <linux/types.h>
12 13
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
L
Linus Torvalds 已提交
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
#include <linux/init.h>
#include <linux/crc32.h>


#define MPEG_VIDEO_TARGET_BITRATE_MAX  27000
#define MPEG_VIDEO_MAX_BITRATE_MAX     27000
#define MPEG_TOTAL_TARGET_BITRATE_MAX  27000
#define MPEG_PID_MAX ((1 << 14) - 1)

/* Addresses to scan */
static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END};
I2C_CLIENT_INSMOD;

MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
MODULE_AUTHOR("Andrew de Quincey");
MODULE_LICENSE("GPL");

static struct i2c_driver driver;
static struct i2c_client client_template;

34 35 36 37 38 39 40 41 42 43
enum saa6752hs_videoformat {
	SAA6752HS_VF_D1 = 0,    /* standard D1 video format: 720x576 */
	SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
	SAA6752HS_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */
	SAA6752HS_VF_SIF = 3,   /* SIF video format: 352x288 */
	SAA6752HS_VF_UNKNOWN,
};

static const struct v4l2_format v4l2_format_table[] =
{
44 45 46 47 48 49 50 51 52 53
	[SAA6752HS_VF_D1] =
		{ .fmt = { .pix = { .width = 720, .height = 576 }}},
	[SAA6752HS_VF_2_3_D1] =
		{ .fmt = { .pix = { .width = 480, .height = 576 }}},
	[SAA6752HS_VF_1_2_D1] =
		{ .fmt = { .pix = { .width = 352, .height = 576 }}},
	[SAA6752HS_VF_SIF] =
		{ .fmt = { .pix = { .width = 352, .height = 288 }}},
	[SAA6752HS_VF_UNKNOWN] =
		{ .fmt = { .pix = { .width = 0, .height = 0}}},
54 55
};

L
Linus Torvalds 已提交
56 57 58
struct saa6752hs_state {
	struct i2c_client             client;
	struct v4l2_mpeg_compression  params;
59
	enum saa6752hs_videoformat    video_format;
60
	v4l2_std_id                   standard;
L
Linus Torvalds 已提交
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
};

enum saa6752hs_command {
	SAA6752HS_COMMAND_RESET = 0,
    	SAA6752HS_COMMAND_STOP = 1,
    	SAA6752HS_COMMAND_START = 2,
    	SAA6752HS_COMMAND_PAUSE = 3,
    	SAA6752HS_COMMAND_RECONFIGURE = 4,
    	SAA6752HS_COMMAND_SLEEP = 5,
	SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,

	SAA6752HS_COMMAND_MAX
};

/* ---------------------------------------------------------------------- */

static u8 PAT[] = {
78 79
	0xc2, /* i2c register */
	0x00, /* table number for encoder */
L
Linus Torvalds 已提交
80

81 82 83
	0x47, /* sync */
	0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) */
	0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
L
Linus Torvalds 已提交
84

85
	0x00, /* PSI pointer to start of table */
L
Linus Torvalds 已提交
86

87 88
	0x00, /* tid(0) */
	0xb0, 0x0d, /* section_syntax_indicator(1), section_length(13) */
L
Linus Torvalds 已提交
89

90
	0x00, 0x01, /* transport_stream_id(1) */
L
Linus Torvalds 已提交
91

92
	0xc1, /* version_number(0), current_next_indicator(1) */
L
Linus Torvalds 已提交
93

94
	0x00, 0x00, /* section_number(0), last_section_number(0) */
L
Linus Torvalds 已提交
95

96
	0x00, 0x01, /* program_number(1) */
L
Linus Torvalds 已提交
97

98
	0xe0, 0x00, /* PMT PID */
L
Linus Torvalds 已提交
99

100
	0x00, 0x00, 0x00, 0x00 /* CRC32 */
L
Linus Torvalds 已提交
101 102 103
};

static u8 PMT[] = {
104 105
	0xc2, /* i2c register */
	0x01, /* table number for encoder */
L
Linus Torvalds 已提交
106

107 108 109
	0x47, /* sync */
	0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid */
	0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
L
Linus Torvalds 已提交
110

111
	0x00, /* PSI pointer to start of table */
L
Linus Torvalds 已提交
112

113 114
	0x02, /* tid(2) */
	0xb0, 0x17, /* section_syntax_indicator(1), section_length(23) */
L
Linus Torvalds 已提交
115

116
	0x00, 0x01, /* program_number(1) */
L
Linus Torvalds 已提交
117

118
	0xc1, /* version_number(0), current_next_indicator(1) */
L
Linus Torvalds 已提交
119

120
	0x00, 0x00, /* section_number(0), last_section_number(0) */
L
Linus Torvalds 已提交
121

122
	0xe0, 0x00, /* PCR_PID */
L
Linus Torvalds 已提交
123

124
	0xf0, 0x00, /* program_info_length(0) */
L
Linus Torvalds 已提交
125

126 127
	0x02, 0xe0, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
	0x04, 0xe0, 0x00, 0xf0, 0x00, /* audio stream type(4), pid */
L
Linus Torvalds 已提交
128

129
	0x00, 0x00, 0x00, 0x00 /* CRC32 */
L
Linus Torvalds 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
};

static struct v4l2_mpeg_compression param_defaults =
{
	.st_type         = V4L2_MPEG_TS_2,
	.st_bitrate      = {
		.mode    = V4L2_BITRATE_CBR,
		.target  = 7000,
	},

	.ts_pid_pmt      = 16,
	.ts_pid_video    = 260,
	.ts_pid_audio    = 256,
	.ts_pid_pcr      = 259,

	.vi_type         = V4L2_MPEG_VI_2,
	.vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3,
	.vi_bitrate      = {
		.mode    = V4L2_BITRATE_VBR,
		.target  = 4000,
		.max     = 6000,
	},

	.au_type         = V4L2_MPEG_AU_2_II,
	.au_bitrate      = {
		.mode    = V4L2_BITRATE_CBR,
		.target  = 256,
	},

};

/* ---------------------------------------------------------------------- */

static int saa6752hs_chip_command(struct i2c_client* client,
				  enum saa6752hs_command command)
{
	unsigned char buf[3];
	unsigned long timeout;
	int status = 0;

170
	/* execute the command */
L
Linus Torvalds 已提交
171
	switch(command) {
172 173
	case SAA6752HS_COMMAND_RESET:
		buf[0] = 0x00;
L
Linus Torvalds 已提交
174 175 176
		break;

	case SAA6752HS_COMMAND_STOP:
177
		buf[0] = 0x03;
L
Linus Torvalds 已提交
178 179 180
		break;

	case SAA6752HS_COMMAND_START:
181
		buf[0] = 0x02;
L
Linus Torvalds 已提交
182 183 184
		break;

	case SAA6752HS_COMMAND_PAUSE:
185
		buf[0] = 0x04;
L
Linus Torvalds 已提交
186 187 188 189 190 191
		break;

	case SAA6752HS_COMMAND_RECONFIGURE:
		buf[0] = 0x05;
		break;

192 193
	case SAA6752HS_COMMAND_SLEEP:
		buf[0] = 0x06;
L
Linus Torvalds 已提交
194 195
		break;

196
	case SAA6752HS_COMMAND_RECONFIGURE_FORCE:
L
Linus Torvalds 已提交
197 198 199 200 201 202 203
		buf[0] = 0x07;
		break;

	default:
		return -EINVAL;
	}

204
	/* set it and wait for it to be so */
L
Linus Torvalds 已提交
205 206 207
	i2c_master_send(client, buf, 1);
	timeout = jiffies + HZ * 3;
	for (;;) {
208
		/* get the current status */
L
Linus Torvalds 已提交
209
		buf[0] = 0x10;
210
		i2c_master_send(client, buf, 1);
L
Linus Torvalds 已提交
211 212 213 214 215 216 217 218 219 220 221 222
		i2c_master_recv(client, buf, 1);

		if (!(buf[0] & 0x20))
			break;
		if (time_after(jiffies,timeout)) {
			status = -ETIMEDOUT;
			break;
		}

		msleep(10);
	}

223
	/* delay a bit to let encoder settle */
L
Linus Torvalds 已提交
224 225
	msleep(50);

226
	return status;
L
Linus Torvalds 已提交
227 228 229 230 231 232
}


static int saa6752hs_set_bitrate(struct i2c_client* client,
				 struct v4l2_mpeg_compression* params)
{
233
	u8 buf[3];
L
Linus Torvalds 已提交
234

235
	/* set the bitrate mode */
L
Linus Torvalds 已提交
236 237 238 239
	buf[0] = 0x71;
	buf[1] = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? 0 : 1;
	i2c_master_send(client, buf, 2);

240
	/* set the video bitrate */
L
Linus Torvalds 已提交
241
	if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) {
242
		/* set the target bitrate */
L
Linus Torvalds 已提交
243 244
		buf[0] = 0x80;
	    	buf[1] = params->vi_bitrate.target >> 8;
245
		buf[2] = params->vi_bitrate.target & 0xff;
L
Linus Torvalds 已提交
246 247
		i2c_master_send(client, buf, 3);

248
		/* set the max bitrate */
L
Linus Torvalds 已提交
249 250
		buf[0] = 0x81;
	    	buf[1] = params->vi_bitrate.max >> 8;
251
		buf[2] = params->vi_bitrate.max & 0xff;
L
Linus Torvalds 已提交
252 253
		i2c_master_send(client, buf, 3);
	} else {
254
		/* set the target bitrate (no max bitrate for CBR) */
255
		buf[0] = 0x81;
L
Linus Torvalds 已提交
256
	    	buf[1] = params->vi_bitrate.target >> 8;
257
		buf[2] = params->vi_bitrate.target & 0xff;
L
Linus Torvalds 已提交
258 259 260
		i2c_master_send(client, buf, 3);
	}

261
	/* set the audio bitrate */
262
	buf[0] = 0x94;
L
Linus Torvalds 已提交
263 264 265
	buf[1] = (256 == params->au_bitrate.target) ? 0 : 1;
	i2c_master_send(client, buf, 2);

266
	/* set the total bitrate */
L
Linus Torvalds 已提交
267
	buf[0] = 0xb1;
268 269
	buf[1] = params->st_bitrate.target >> 8;
	buf[2] = params->st_bitrate.target & 0xff;
L
Linus Torvalds 已提交
270 271 272 273 274
	i2c_master_send(client, buf, 3);

	return 0;
}

275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
static void saa6752hs_set_subsampling(struct i2c_client* client,
				      struct v4l2_format* f)
{
	struct saa6752hs_state *h = i2c_get_clientdata(client);
	int dist_352, dist_480, dist_720;

	/*
	  FIXME: translate and round width/height into EMPRESS
	  subsample type:

	  type   |   PAL   |  NTSC
	  ---------------------------
	  SIF    | 352x288 | 352x240
	  1/2 D1 | 352x576 | 352x480
	  2/3 D1 | 480x576 | 480x480
	  D1     | 720x576 | 720x480
	*/

	dist_352 = abs(f->fmt.pix.width - 352);
	dist_480 = abs(f->fmt.pix.width - 480);
	dist_720 = abs(f->fmt.pix.width - 720);
	if (dist_720 < dist_480) {
		f->fmt.pix.width = 720;
		f->fmt.pix.height = 576;
		h->video_format = SAA6752HS_VF_D1;
	}
	else if (dist_480 < dist_352) {
		f->fmt.pix.width = 480;
		f->fmt.pix.height = 576;
		h->video_format = SAA6752HS_VF_2_3_D1;
	}
	else {
		f->fmt.pix.width = 352;
		if (abs(f->fmt.pix.height - 576) <
		    abs(f->fmt.pix.height - 288)) {
			f->fmt.pix.height = 576;
			h->video_format = SAA6752HS_VF_1_2_D1;
		}
		else {
			f->fmt.pix.height = 288;
			h->video_format = SAA6752HS_VF_SIF;
		}
	}
}

L
Linus Torvalds 已提交
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376

static void saa6752hs_set_params(struct i2c_client* client,
				 struct v4l2_mpeg_compression* params)
{
	struct saa6752hs_state *h = i2c_get_clientdata(client);

	/* check PIDs */
	if (params->ts_pid_pmt <= MPEG_PID_MAX)
		h->params.ts_pid_pmt = params->ts_pid_pmt;
	if (params->ts_pid_pcr <= MPEG_PID_MAX)
		h->params.ts_pid_pcr = params->ts_pid_pcr;
	if (params->ts_pid_video <= MPEG_PID_MAX)
		h->params.ts_pid_video = params->ts_pid_video;
	if (params->ts_pid_audio <= MPEG_PID_MAX)
		h->params.ts_pid_audio = params->ts_pid_audio;

	/* check bitrate parameters */
	if ((params->vi_bitrate.mode == V4L2_BITRATE_CBR) ||
	    (params->vi_bitrate.mode == V4L2_BITRATE_VBR))
		h->params.vi_bitrate.mode = params->vi_bitrate.mode;
	if (params->vi_bitrate.mode != V4L2_BITRATE_NONE)
		h->params.st_bitrate.target = params->st_bitrate.target;
	if (params->vi_bitrate.mode != V4L2_BITRATE_NONE)
		h->params.vi_bitrate.target = params->vi_bitrate.target;
	if (params->vi_bitrate.mode == V4L2_BITRATE_VBR)
		h->params.vi_bitrate.max = params->vi_bitrate.max;
	if (params->au_bitrate.mode != V4L2_BITRATE_NONE)
		h->params.au_bitrate.target = params->au_bitrate.target;

	/* aspect ratio */
	if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3 ||
	    params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9)
		h->params.vi_aspect_ratio = params->vi_aspect_ratio;

	/* range checks */
	if (h->params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX)
		h->params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX;
	if (h->params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX)
		h->params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX;
	if (h->params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX)
		h->params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX;
	if (h->params.au_bitrate.target <= 256)
		h->params.au_bitrate.target = 256;
	else
		h->params.au_bitrate.target = 384;
}

static int saa6752hs_init(struct i2c_client* client)
{
	unsigned char buf[9], buf2[4];
	struct saa6752hs_state *h;
	u32 crc;
	unsigned char localPAT[256];
	unsigned char localPMT[256];

	h = i2c_get_clientdata(client);

377
	/* Set video format - must be done first as it resets other settings */
L
Linus Torvalds 已提交
378
	buf[0] = 0x41;
379
	buf[1] = h->video_format;
L
Linus Torvalds 已提交
380 381
	i2c_master_send(client, buf, 2);

382 383 384 385 386 387 388
	/* Set number of lines in input signal */
	buf[0] = 0x40;
	buf[1] = 0x00;
	if (h->standard & V4L2_STD_525_60)
		buf[1] = 0x01;
	i2c_master_send(client, buf, 2);

389 390
	/* set bitrate */
	saa6752hs_set_bitrate(client, &h->params);
L
Linus Torvalds 已提交
391

392
	/* Set GOP structure {3, 13} */
L
Linus Torvalds 已提交
393 394 395 396 397
	buf[0] = 0x72;
	buf[1] = 0x03;
	buf[2] = 0x0D;
	i2c_master_send(client,buf,3);

398
    	/* Set minimum Q-scale {4} */
L
Linus Torvalds 已提交
399 400 401 402
	buf[0] = 0x82;
	buf[1] = 0x04;
	i2c_master_send(client,buf,2);

403
    	/* Set maximum Q-scale {12} */
L
Linus Torvalds 已提交
404 405 406 407
	buf[0] = 0x83;
	buf[1] = 0x0C;
	i2c_master_send(client,buf,2);

408
    	/* Set Output Protocol */
L
Linus Torvalds 已提交
409 410 411 412
	buf[0] = 0xD0;
	buf[1] = 0x81;
	i2c_master_send(client,buf,2);

413
    	/* Set video output stream format {TS} */
L
Linus Torvalds 已提交
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
	buf[0] = 0xB0;
	buf[1] = 0x05;
	i2c_master_send(client,buf,2);

	/* compute PAT */
	memcpy(localPAT, PAT, sizeof(PAT));
	localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
	localPAT[18] = h->params.ts_pid_pmt & 0xff;
	crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);
	localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
	localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
	localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
	localPAT[sizeof(PAT) - 1] = crc & 0xFF;

	/* compute PMT */
429 430 431
	memcpy(localPMT, PMT, sizeof(PMT));
	localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
	localPMT[4] = h->params.ts_pid_pmt & 0xff;
L
Linus Torvalds 已提交
432 433 434 435 436 437 438 439 440 441 442 443
	localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);
	localPMT[16] = h->params.ts_pid_pcr & 0xFF;
	localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F);
	localPMT[21] = h->params.ts_pid_video & 0xFF;
	localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);
	localPMT[26] = h->params.ts_pid_audio & 0xFF;
	crc = crc32_be(~0, &localPMT[7], sizeof(PMT) - 7 - 4);
	localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF;
	localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF;
	localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
	localPMT[sizeof(PMT) - 1] = crc & 0xFF;

444
    	/* Set Audio PID */
L
Linus Torvalds 已提交
445 446 447 448 449
	buf[0] = 0xC1;
	buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF;
	buf[2] = h->params.ts_pid_audio & 0xFF;
	i2c_master_send(client,buf,3);

450
	/* Set Video PID */
L
Linus Torvalds 已提交
451 452 453 454 455
	buf[0] = 0xC0;
	buf[1] = (h->params.ts_pid_video >> 8) & 0xFF;
	buf[2] = h->params.ts_pid_video & 0xFF;
	i2c_master_send(client,buf,3);

456
	/* Set PCR PID */
L
Linus Torvalds 已提交
457 458 459 460 461
	buf[0] = 0xC4;
	buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF;
	buf[2] = h->params.ts_pid_pcr & 0xFF;
	i2c_master_send(client,buf,3);

462
	/* Send SI tables */
L
Linus Torvalds 已提交
463 464 465
	i2c_master_send(client,localPAT,sizeof(PAT));
	i2c_master_send(client,localPMT,sizeof(PMT));

466
	/* mute then unmute audio. This removes buzzing artefacts */
L
Linus Torvalds 已提交
467 468 469
	buf[0] = 0xa4;
	buf[1] = 1;
	i2c_master_send(client, buf, 2);
470
	buf[1] = 0;
L
Linus Torvalds 已提交
471 472
	i2c_master_send(client, buf, 2);

473
	/* start it going */
L
Linus Torvalds 已提交
474 475
	saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);

476
	/* readout current state */
L
Linus Torvalds 已提交
477 478 479 480 481 482 483 484
	buf[0] = 0xE1;
	buf[1] = 0xA7;
	buf[2] = 0xFE;
	buf[3] = 0x82;
	buf[4] = 0xB0;
	i2c_master_send(client, buf, 5);
	i2c_master_recv(client, buf2, 4);

485
	/* change aspect ratio */
L
Linus Torvalds 已提交
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
	buf[0] = 0xE0;
	buf[1] = 0xA7;
	buf[2] = 0xFE;
	buf[3] = 0x82;
	buf[4] = 0xB0;
	buf[5] = buf2[0];
	switch(h->params.vi_aspect_ratio) {
	case V4L2_MPEG_ASPECT_16_9:
		buf[6] = buf2[1] | 0x40;
		break;
	case V4L2_MPEG_ASPECT_4_3:
	default:
		buf[6] = buf2[1] & 0xBF;
		break;
		break;
	}
	buf[7] = buf2[2];
	buf[8] = buf2[3];
	i2c_master_send(client, buf, 9);

	return 0;
}

static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
{
	struct saa6752hs_state *h;


514 515
	if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL)))
		return -ENOMEM;
L
Linus Torvalds 已提交
516 517 518 519 520 521
	memset(h,0,sizeof(*h));
	h->client = client_template;
	h->params = param_defaults;
	h->client.adapter = adap;
	h->client.addr = addr;

522 523 524
	/* Assume 625 input lines */
	h->standard = 0;

L
Linus Torvalds 已提交
525
	i2c_set_clientdata(&h->client, h);
526
	i2c_attach_client(&h->client);
527

528 529
	v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1);

L
Linus Torvalds 已提交
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
	return 0;
}

static int saa6752hs_probe(struct i2c_adapter *adap)
{
	if (adap->class & I2C_CLASS_TV_ANALOG)
		return i2c_probe(adap, &addr_data, saa6752hs_attach);
	return 0;
}

static int saa6752hs_detach(struct i2c_client *client)
{
	struct saa6752hs_state *h;

	h = i2c_get_clientdata(client);
	i2c_detach_client(client);
	kfree(h);
	return 0;
}

static int
saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
	struct saa6752hs_state *h = i2c_get_clientdata(client);
	struct v4l2_mpeg_compression *params = arg;
	int err = 0;

557
	switch (cmd) {
L
Linus Torvalds 已提交
558 559 560 561 562 563 564 565 566 567 568
	case VIDIOC_S_MPEGCOMP:
		if (NULL == params) {
			/* apply settings and start encoder */
			saa6752hs_init(client);
			break;
		}
		saa6752hs_set_params(client, params);
		/* fall through */
	case VIDIOC_G_MPEGCOMP:
		*params = h->params;
		break;
569 570
	case VIDIOC_G_FMT:
	{
571
	   struct v4l2_format *f = arg;
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587

	   if (h->video_format == SAA6752HS_VF_UNKNOWN)
		   h->video_format = SAA6752HS_VF_D1;
	   f->fmt.pix.width =
		   v4l2_format_table[h->video_format].fmt.pix.width;
	   f->fmt.pix.height =
		   v4l2_format_table[h->video_format].fmt.pix.height;
	   break ;
	}
	case VIDIOC_S_FMT:
	{
		struct v4l2_format *f = arg;

		saa6752hs_set_subsampling(client, f);
		break;
	}
588 589 590
	case VIDIOC_S_STD:
		h->standard = *((v4l2_std_id *) arg);
		break;
L
Linus Torvalds 已提交
591 592 593 594 595 596 597 598 599 600 601
	default:
		/* nothing */
		break;
	}

	return err;
}

/* ----------------------------------------------------------------------- */

static struct i2c_driver driver = {
602
	.driver = {
603
		.name   = "saa6752hs",
604
	},
605 606 607 608
	.id             = I2C_DRIVERID_SAA6752HS,
	.attach_adapter = saa6752hs_probe,
	.detach_client  = saa6752hs_detach,
	.command        = saa6752hs_command,
L
Linus Torvalds 已提交
609 610 611 612
};

static struct i2c_client client_template =
{
613
	.name       = "saa6752hs",
614
	.driver     = &driver,
L
Linus Torvalds 已提交
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
};

static int __init saa6752hs_init_module(void)
{
	return i2c_add_driver(&driver);
}

static void __exit saa6752hs_cleanup_module(void)
{
	i2c_del_driver(&driver);
}

module_init(saa6752hs_init_module);
module_exit(saa6752hs_cleanup_module);

/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-basic-offset: 8
 * End:
 */