saa6752hs.c 15.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
#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>
#include <linux/videodev.h>
#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;

33 34 35 36 37 38 39 40 41 42
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[] =
{
43 44 45 46 47 48 49 50 51 52
	[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}}},
53 54
};

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

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[] = {
77 78
	0xc2, /* i2c register */
	0x00, /* table number for encoder */
L
Linus Torvalds 已提交
79

80 81 82
	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 已提交
83

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

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

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

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

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

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

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

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

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

106 107 108
	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 已提交
109

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

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

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

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

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

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

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

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

128
	0x00, 0x00, 0x00, 0x00 /* CRC32 */
L
Linus Torvalds 已提交
129 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
};

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;

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

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

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

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

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

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

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

	default:
		return -EINVAL;
	}

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

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

		msleep(10);
	}

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

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


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

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

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

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

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

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

	return 0;
}

274 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
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 已提交
319 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

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);

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

381 382 383 384 385 386 387
	/* 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);

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

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

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

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

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

412
    	/* Set video output stream format {TS} */
L
Linus Torvalds 已提交
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
	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 */
428 429 430
	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 已提交
431 432 433 434 435 436 437 438 439 440 441 442
	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;

443
    	/* Set Audio PID */
L
Linus Torvalds 已提交
444 445 446 447 448
	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);

449
	/* Set Video PID */
L
Linus Torvalds 已提交
450 451 452 453 454
	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);

455
	/* Set PCR PID */
L
Linus Torvalds 已提交
456 457 458 459 460
	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);

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

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

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

475
	/* readout current state */
L
Linus Torvalds 已提交
476 477 478 479 480 481 482 483
	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);

484
	/* change aspect ratio */
L
Linus Torvalds 已提交
485 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
	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;

512
	printk("saa6752hs: chip found @ 0x%x\n", addr<<1);
L
Linus Torvalds 已提交
513

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

L
Linus Torvalds 已提交
528 529 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
	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;

555
	switch (cmd) {
L
Linus Torvalds 已提交
556 557 558 559 560 561 562 563 564 565 566
	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;
567 568
	case VIDIOC_G_FMT:
	{
569
	   struct v4l2_format *f = arg;
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585

	   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;
	}
586 587 588
	case VIDIOC_S_STD:
		h->standard = *((v4l2_std_id *) arg);
		break;
L
Linus Torvalds 已提交
589 590 591 592 593 594 595 596 597 598 599
	default:
		/* nothing */
		break;
	}

	return err;
}

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

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

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

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:
 */