brintos

brintos / linux-shallow public Read only

0
0
Text · 43.1 KiB · 965d285 Raw
1513 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  Driver for the NXP SAA7164 PCIe bridge4 *5 *  Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>6 */7 8#include <linux/wait.h>9#include <linux/slab.h>10 11#include "saa7164.h"12 13int saa7164_api_get_load_info(struct saa7164_dev *dev, struct tmFwInfoStruct *i)14{15	int ret;16 17	if (!(saa_debug & DBGLVL_CPU))18		return 0;19 20	dprintk(DBGLVL_API, "%s()\n", __func__);21 22	i->deviceinst = 0;23	i->devicespec = 0;24	i->mode = 0;25	i->status = 0;26 27	ret = saa7164_cmd_send(dev, 0, GET_CUR,28		GET_FW_STATUS_CONTROL, sizeof(struct tmFwInfoStruct), i);29	if (ret != SAA_OK)30		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);31 32	printk(KERN_INFO "saa7164[%d]-CPU: %d percent", dev->nr, i->CPULoad);33 34	return ret;35}36 37int saa7164_api_collect_debug(struct saa7164_dev *dev)38{39	struct tmComResDebugGetData d;40	u8 more = 255;41	int ret;42 43	dprintk(DBGLVL_API, "%s()\n", __func__);44 45	while (more--) {46 47		memset(&d, 0, sizeof(d));48 49		ret = saa7164_cmd_send(dev, 0, GET_CUR,50			GET_DEBUG_DATA_CONTROL, sizeof(d), &d);51		if (ret != SAA_OK)52			printk(KERN_ERR "%s() error, ret = 0x%x\n",53				__func__, ret);54 55		if (d.dwResult != SAA_OK)56			break;57 58		printk(KERN_INFO "saa7164[%d]-FWMSG: %s", dev->nr,59			d.ucDebugData);60	}61 62	return 0;63}64 65int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level)66{67	struct tmComResDebugSetLevel lvl;68	int ret;69 70	dprintk(DBGLVL_API, "%s(level=%d)\n", __func__, level);71 72	/* Retrieve current state */73	ret = saa7164_cmd_send(dev, 0, GET_CUR,74		SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl);75	if (ret != SAA_OK)76		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);77 78	dprintk(DBGLVL_API, "%s() Was %d\n", __func__, lvl.dwDebugLevel);79 80	lvl.dwDebugLevel = level;81 82	/* set new state */83	ret = saa7164_cmd_send(dev, 0, SET_CUR,84		SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl);85	if (ret != SAA_OK)86		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);87 88	return ret;89}90 91int saa7164_api_set_vbi_format(struct saa7164_port *port)92{93	struct saa7164_dev *dev = port->dev;94	struct tmComResProbeCommit fmt, rsp;95	int ret;96 97	dprintk(DBGLVL_API, "%s(nr=%d, unitid=0x%x)\n", __func__,98		port->nr, port->hwcfg.unitid);99 100	fmt.bmHint = 0;101	fmt.bFormatIndex = 1;102	fmt.bFrameIndex = 1;103 104	/* Probe, see if it can support this format */105	ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,106		SET_CUR, SAA_PROBE_CONTROL, sizeof(fmt), &fmt);107	if (ret != SAA_OK)108		printk(KERN_ERR "%s() set error, ret = 0x%x\n", __func__, ret);109 110	/* See of the format change was successful */111	ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,112		GET_CUR, SAA_PROBE_CONTROL, sizeof(rsp), &rsp);113	if (ret != SAA_OK) {114		printk(KERN_ERR "%s() get error, ret = 0x%x\n", __func__, ret);115	} else {116		/* Compare requested vs received, should be same */117		if (memcmp(&fmt, &rsp, sizeof(rsp)) == 0) {118			dprintk(DBGLVL_API, "SET/PROBE Verified\n");119 120			/* Ask the device to select the negotiated format */121			ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,122				SET_CUR, SAA_COMMIT_CONTROL, sizeof(fmt), &fmt);123			if (ret != SAA_OK)124				printk(KERN_ERR "%s() commit error, ret = 0x%x\n",125					__func__, ret);126 127			ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,128				GET_CUR, SAA_COMMIT_CONTROL, sizeof(rsp), &rsp);129			if (ret != SAA_OK)130				printk(KERN_ERR "%s() GET commit error, ret = 0x%x\n",131					__func__, ret);132 133			if (memcmp(&fmt, &rsp, sizeof(rsp)) != 0) {134				printk(KERN_ERR "%s() memcmp error, ret = 0x%x\n",135					__func__, ret);136			} else137				dprintk(DBGLVL_API, "SET/COMMIT Verified\n");138 139			dprintk(DBGLVL_API, "rsp.bmHint = 0x%x\n", rsp.bmHint);140			dprintk(DBGLVL_API, "rsp.bFormatIndex = 0x%x\n",141				rsp.bFormatIndex);142			dprintk(DBGLVL_API, "rsp.bFrameIndex = 0x%x\n",143				rsp.bFrameIndex);144		} else145			printk(KERN_ERR "%s() compare failed\n", __func__);146	}147 148	if (ret == SAA_OK)149		dprintk(DBGLVL_API, "%s(nr=%d) Success\n", __func__, port->nr);150 151	return ret;152}153 154static int saa7164_api_set_gop_size(struct saa7164_port *port)155{156	struct saa7164_dev *dev = port->dev;157	struct tmComResEncVideoGopStructure gs;158	int ret;159 160	dprintk(DBGLVL_ENC, "%s()\n", __func__);161 162	gs.ucRefFrameDist = port->encoder_params.refdist;163	gs.ucGOPSize = port->encoder_params.gop_size;164	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,165		EU_VIDEO_GOP_STRUCTURE_CONTROL,166		sizeof(gs), &gs);167	if (ret != SAA_OK)168		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);169 170	return ret;171}172 173int saa7164_api_set_encoder(struct saa7164_port *port)174{175	struct saa7164_dev *dev = port->dev;176	struct tmComResEncVideoBitRate vb;177	struct tmComResEncAudioBitRate ab;178	int ret;179 180	dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__,181		port->hwcfg.sourceid);182 183	if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS)184		port->encoder_profile = EU_PROFILE_PS_DVD;185	else186		port->encoder_profile = EU_PROFILE_TS_HQ;187 188	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,189		EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);190	if (ret != SAA_OK)191		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);192 193	/* Resolution */194	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,195		EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);196	if (ret != SAA_OK)197		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);198 199	/* Establish video bitrates */200	if (port->encoder_params.bitrate_mode ==201		V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)202		vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_CONSTANT;203	else204		vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK;205	vb.dwVideoBitRate = port->encoder_params.bitrate;206	vb.dwVideoBitRatePeak = port->encoder_params.bitrate_peak;207	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,208		EU_VIDEO_BIT_RATE_CONTROL,209		sizeof(struct tmComResEncVideoBitRate),210		&vb);211	if (ret != SAA_OK)212		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);213 214	/* Establish audio bitrates */215	ab.ucAudioBitRateMode = 0;216	ab.dwAudioBitRate = 384000;217	ab.dwAudioBitRatePeak = ab.dwAudioBitRate;218	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,219		EU_AUDIO_BIT_RATE_CONTROL,220		sizeof(struct tmComResEncAudioBitRate),221		&ab);222	if (ret != SAA_OK)223		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,224			ret);225 226	saa7164_api_set_aspect_ratio(port);227	saa7164_api_set_gop_size(port);228 229	return ret;230}231 232int saa7164_api_get_encoder(struct saa7164_port *port)233{234	struct saa7164_dev *dev = port->dev;235	struct tmComResEncVideoBitRate v;236	struct tmComResEncAudioBitRate a;237	struct tmComResEncVideoInputAspectRatio ar;238	int ret;239 240	dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__,241		port->hwcfg.sourceid);242 243	port->encoder_profile = 0;244	port->video_format = 0;245	port->video_resolution = 0;246	port->audio_format = 0;247 248	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,249		EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);250	if (ret != SAA_OK)251		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);252 253	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,254		EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8),255		&port->video_resolution);256	if (ret != SAA_OK)257		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);258 259	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,260		EU_VIDEO_FORMAT_CONTROL, sizeof(u8), &port->video_format);261	if (ret != SAA_OK)262		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);263 264	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,265		EU_VIDEO_BIT_RATE_CONTROL, sizeof(v), &v);266	if (ret != SAA_OK)267		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);268 269	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,270		EU_AUDIO_FORMAT_CONTROL, sizeof(u8), &port->audio_format);271	if (ret != SAA_OK)272		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);273 274	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,275		EU_AUDIO_BIT_RATE_CONTROL, sizeof(a), &a);276	if (ret != SAA_OK)277		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);278 279	/* Aspect Ratio */280	ar.width = 0;281	ar.height = 0;282	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,283		EU_VIDEO_INPUT_ASPECT_CONTROL,284		sizeof(struct tmComResEncVideoInputAspectRatio), &ar);285	if (ret != SAA_OK)286		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);287 288	dprintk(DBGLVL_ENC, "encoder_profile = %d\n", port->encoder_profile);289	dprintk(DBGLVL_ENC, "video_format    = %d\n", port->video_format);290	dprintk(DBGLVL_ENC, "audio_format    = %d\n", port->audio_format);291	dprintk(DBGLVL_ENC, "video_resolution= %d\n", port->video_resolution);292	dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n",293		v.ucVideoBitRateMode);294	dprintk(DBGLVL_ENC, "v.dwVideoBitRate     = %d\n",295		v.dwVideoBitRate);296	dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n",297		v.dwVideoBitRatePeak);298	dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n",299		a.ucAudioBitRateMode);300	dprintk(DBGLVL_ENC, "a.dwVideoBitRate     = %d\n",301		a.dwAudioBitRate);302	dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n",303		a.dwAudioBitRatePeak);304	dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n",305		ar.width, ar.height);306 307	return ret;308}309 310int saa7164_api_set_aspect_ratio(struct saa7164_port *port)311{312	struct saa7164_dev *dev = port->dev;313	struct tmComResEncVideoInputAspectRatio ar;314	int ret;315 316	dprintk(DBGLVL_ENC, "%s(%d)\n", __func__,317		port->encoder_params.ctl_aspect);318 319	switch (port->encoder_params.ctl_aspect) {320	case V4L2_MPEG_VIDEO_ASPECT_1x1:321		ar.width = 1;322		ar.height = 1;323		break;324	case V4L2_MPEG_VIDEO_ASPECT_4x3:325		ar.width = 4;326		ar.height = 3;327		break;328	case V4L2_MPEG_VIDEO_ASPECT_16x9:329		ar.width = 16;330		ar.height = 9;331		break;332	case V4L2_MPEG_VIDEO_ASPECT_221x100:333		ar.width = 221;334		ar.height = 100;335		break;336	default:337		BUG();338	}339 340	dprintk(DBGLVL_ENC, "%s(%d) now %d:%d\n", __func__,341		port->encoder_params.ctl_aspect,342		ar.width, ar.height);343 344	/* Aspect Ratio */345	ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,346		EU_VIDEO_INPUT_ASPECT_CONTROL,347		sizeof(struct tmComResEncVideoInputAspectRatio), &ar);348	if (ret != SAA_OK)349		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);350 351	return ret;352}353 354int saa7164_api_set_usercontrol(struct saa7164_port *port, u8 ctl)355{356	struct saa7164_dev *dev = port->dev;357	int ret;358	u16 val;359 360	if (ctl == PU_BRIGHTNESS_CONTROL)361		val = port->ctl_brightness;362	else363	if (ctl == PU_CONTRAST_CONTROL)364		val = port->ctl_contrast;365	else366	if (ctl == PU_HUE_CONTROL)367		val = port->ctl_hue;368	else369	if (ctl == PU_SATURATION_CONTROL)370		val = port->ctl_saturation;371	else372	if (ctl == PU_SHARPNESS_CONTROL)373		val = port->ctl_sharpness;374	else375		return -EINVAL;376 377	dprintk(DBGLVL_ENC, "%s() unitid=0x%x ctl=%d, val=%d\n",378		__func__, port->encunit.vsourceid, ctl, val);379 380	ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, SET_CUR,381		ctl, sizeof(u16), &val);382	if (ret != SAA_OK)383		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);384 385	return ret;386}387 388int saa7164_api_get_usercontrol(struct saa7164_port *port, u8 ctl)389{390	struct saa7164_dev *dev = port->dev;391	int ret;392	u16 val;393 394	ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, GET_CUR,395		ctl, sizeof(u16), &val);396	if (ret != SAA_OK) {397		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);398		return ret;399	}400 401	dprintk(DBGLVL_ENC, "%s() ctl=%d, val=%d\n",402		__func__, ctl, val);403 404	if (ctl == PU_BRIGHTNESS_CONTROL)405		port->ctl_brightness = val;406	else407	if (ctl == PU_CONTRAST_CONTROL)408		port->ctl_contrast = val;409	else410	if (ctl == PU_HUE_CONTROL)411		port->ctl_hue = val;412	else413	if (ctl == PU_SATURATION_CONTROL)414		port->ctl_saturation = val;415	else416	if (ctl == PU_SHARPNESS_CONTROL)417		port->ctl_sharpness = val;418 419	return ret;420}421 422int saa7164_api_set_videomux(struct saa7164_port *port)423{424	struct saa7164_dev *dev = port->dev;425	u8 inputs[] = { 1, 2, 2, 2, 5, 5, 5 };426	int ret;427 428	dprintk(DBGLVL_ENC, "%s() v_mux=%d a_mux=%d\n",429		__func__, port->mux_input, inputs[port->mux_input - 1]);430 431	/* Audio Mute */432	ret = saa7164_api_audio_mute(port, 1);433	if (ret != SAA_OK)434		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);435 436	/* Video Mux */437	ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, SET_CUR,438		SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input);439	if (ret != SAA_OK)440		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);441 442	/* Audio Mux */443	ret = saa7164_cmd_send(port->dev, port->audfeat.sourceid, SET_CUR,444		SU_INPUT_SELECT_CONTROL, sizeof(u8),445		&inputs[port->mux_input - 1]);446	if (ret != SAA_OK)447		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);448 449	/* Audio UnMute */450	ret = saa7164_api_audio_mute(port, 0);451	if (ret != SAA_OK)452		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);453 454	return ret;455}456 457int saa7164_api_audio_mute(struct saa7164_port *port, int mute)458{459	struct saa7164_dev *dev = port->dev;460	u8 v = mute;461	int ret;462 463	dprintk(DBGLVL_API, "%s(%d)\n", __func__, mute);464 465	ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,466		MUTE_CONTROL, sizeof(u8), &v);467	if (ret != SAA_OK)468		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);469 470	return ret;471}472 473/* 0 = silence, 0xff = full */474int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level)475{476	struct saa7164_dev *dev = port->dev;477	s16 v, min, max;478	int ret;479 480	dprintk(DBGLVL_API, "%s(%d)\n", __func__, level);481 482	/* Obtain the min/max ranges */483	ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MIN,484		VOLUME_CONTROL, sizeof(u16), &min);485	if (ret != SAA_OK)486		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);487 488	ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MAX,489		VOLUME_CONTROL, sizeof(u16), &max);490	if (ret != SAA_OK)491		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);492 493	ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR,494		(0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v);495	if (ret != SAA_OK)496		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);497 498	dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__,499		level, min, max, v);500 501	v = level;502	if (v < min)503		v = min;504	if (v > max)505		v = max;506 507	/* Left */508	ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,509		(0x01 << 8) | VOLUME_CONTROL, sizeof(s16), &v);510	if (ret != SAA_OK)511		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);512 513	/* Right */514	ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,515		(0x02 << 8) | VOLUME_CONTROL, sizeof(s16), &v);516	if (ret != SAA_OK)517		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);518 519	ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR,520		(0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v);521	if (ret != SAA_OK)522		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);523 524	dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__,525		level, min, max, v);526 527	return ret;528}529 530int saa7164_api_set_audio_std(struct saa7164_port *port)531{532	struct saa7164_dev *dev = port->dev;533	struct tmComResAudioDefaults lvl;534	struct tmComResTunerStandard tvaudio;535	int ret;536 537	dprintk(DBGLVL_API, "%s()\n", __func__);538 539	/* Establish default levels */540	lvl.ucDecoderLevel = TMHW_LEV_ADJ_DECLEV_DEFAULT;541	lvl.ucDecoderFM_Level = TMHW_LEV_ADJ_DECLEV_DEFAULT;542	lvl.ucMonoLevel = TMHW_LEV_ADJ_MONOLEV_DEFAULT;543	lvl.ucNICAM_Level = TMHW_LEV_ADJ_NICLEV_DEFAULT;544	lvl.ucSAP_Level = TMHW_LEV_ADJ_SAPLEV_DEFAULT;545	lvl.ucADC_Level = TMHW_LEV_ADJ_ADCLEV_DEFAULT;546	ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,547		AUDIO_DEFAULT_CONTROL, sizeof(struct tmComResAudioDefaults),548		&lvl);549	if (ret != SAA_OK)550		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);551 552	/* Manually select the appropriate TV audio standard */553	if (port->encodernorm.id & V4L2_STD_NTSC) {554		tvaudio.std = TU_STANDARD_NTSC_M;555		tvaudio.country = 1;556	} else {557		tvaudio.std = TU_STANDARD_PAL_I;558		tvaudio.country = 44;559	}560 561	ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,562		TU_STANDARD_CONTROL, sizeof(tvaudio), &tvaudio);563	if (ret != SAA_OK)564		printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n",565			__func__, ret);566	return ret;567}568 569int saa7164_api_set_audio_detection(struct saa7164_port *port, int autodetect)570{571	struct saa7164_dev *dev = port->dev;572	struct tmComResTunerStandardAuto p;573	int ret;574 575	dprintk(DBGLVL_API, "%s(%d)\n", __func__, autodetect);576 577	/* Disable TV Audio autodetect if not already set (buggy) */578	if (autodetect)579		p.mode = TU_STANDARD_AUTO;580	else581		p.mode = TU_STANDARD_MANUAL;582	ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,583		TU_STANDARD_AUTO_CONTROL, sizeof(p), &p);584	if (ret != SAA_OK)585		printk(KERN_ERR586			"%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n",587			__func__, ret);588 589	return ret;590}591 592int saa7164_api_get_videomux(struct saa7164_port *port)593{594	struct saa7164_dev *dev = port->dev;595	int ret;596 597	ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, GET_CUR,598		SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input);599	if (ret != SAA_OK)600		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);601 602	dprintk(DBGLVL_ENC, "%s() v_mux=%d\n",603		__func__, port->mux_input);604 605	return ret;606}607 608static int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val)609{610	struct saa7164_dev *dev = port->dev;611 612	u16 len = 0;613	u8 buf[256];614	int ret;615	u8 mas;616 617	dprintk(DBGLVL_API, "%s(nr=%d type=%d val=%x)\n", __func__,618		port->nr, port->type, val);619 620	if (port->nr == 0)621		mas = 0xd0;622	else623		mas = 0xe0;624 625	memset(buf, 0, sizeof(buf));626 627	buf[0x00] = 0x04;628	buf[0x01] = 0x00;629	buf[0x02] = 0x00;630	buf[0x03] = 0x00;631 632	buf[0x04] = 0x04;633	buf[0x05] = 0x00;634	buf[0x06] = 0x00;635	buf[0x07] = 0x00;636 637	buf[0x08] = reg;638	buf[0x09] = 0x26;639	buf[0x0a] = mas;640	buf[0x0b] = 0xb0;641 642	buf[0x0c] = val;643	buf[0x0d] = 0x00;644	buf[0x0e] = 0x00;645	buf[0x0f] = 0x00;646 647	ret = saa7164_cmd_send(dev, port->ifunit.unitid, GET_LEN,648		EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);649	if (ret != SAA_OK) {650		printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);651		return -EIO;652	}653 654	ret = saa7164_cmd_send(dev, port->ifunit.unitid, SET_CUR,655		EXU_REGISTER_ACCESS_CONTROL, len, &buf);656	if (ret != SAA_OK)657		printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);658#if 0659	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf, 16,660		       false);661#endif662	return ret == SAA_OK ? 0 : -EIO;663}664 665/* Disable the IF block AGC controls */666int saa7164_api_configure_dif(struct saa7164_port *port, u32 std)667{668	struct saa7164_dev *dev = port->dev;669	u8 agc_disable;670 671	dprintk(DBGLVL_API, "%s(nr=%d, 0x%x)\n", __func__, port->nr, std);672 673	if (std & V4L2_STD_NTSC) {674		dprintk(DBGLVL_API, " NTSC\n");675		saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */676		agc_disable = 0;677	} else if (std & V4L2_STD_PAL_I) {678		dprintk(DBGLVL_API, " PAL-I\n");679		saa7164_api_set_dif(port, 0x00, 0x08); /* Video Standard */680		agc_disable = 0;681	} else if (std & V4L2_STD_PAL_M) {682		dprintk(DBGLVL_API, " PAL-M\n");683		saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */684		agc_disable = 0;685	} else if (std & V4L2_STD_PAL_N) {686		dprintk(DBGLVL_API, " PAL-N\n");687		saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */688		agc_disable = 0;689	} else if (std & V4L2_STD_PAL_Nc) {690		dprintk(DBGLVL_API, " PAL-Nc\n");691		saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */692		agc_disable = 0;693	} else if (std & V4L2_STD_PAL_B) {694		dprintk(DBGLVL_API, " PAL-B\n");695		saa7164_api_set_dif(port, 0x00, 0x02); /* Video Standard */696		agc_disable = 0;697	} else if (std & V4L2_STD_PAL_DK) {698		dprintk(DBGLVL_API, " PAL-DK\n");699		saa7164_api_set_dif(port, 0x00, 0x10); /* Video Standard */700		agc_disable = 0;701	} else if (std & V4L2_STD_SECAM_L) {702		dprintk(DBGLVL_API, " SECAM-L\n");703		saa7164_api_set_dif(port, 0x00, 0x20); /* Video Standard */704		agc_disable = 0;705	} else {706		/* Unknown standard, assume DTV */707		dprintk(DBGLVL_API, " Unknown (assuming DTV)\n");708		/* Undefinded Video Standard */709		saa7164_api_set_dif(port, 0x00, 0x80);710		agc_disable = 1;711	}712 713	saa7164_api_set_dif(port, 0x48, 0xa0); /* AGC Functions 1 */714	saa7164_api_set_dif(port, 0xc0, agc_disable); /* AGC Output Disable */715	saa7164_api_set_dif(port, 0x7c, 0x04); /* CVBS EQ */716	saa7164_api_set_dif(port, 0x04, 0x01); /* Active */717	msleep(100);718	saa7164_api_set_dif(port, 0x04, 0x00); /* Active (again) */719	msleep(100);720 721	return 0;722}723 724/* Ensure the dif is in the correct state for the operating mode725 * (analog / dtv). We only configure the diff through the analog encoder726 * so when we're in digital mode we need to find the appropriate encoder727 * and use it to configure the DIF.728 */729int saa7164_api_initialize_dif(struct saa7164_port *port)730{731	struct saa7164_dev *dev = port->dev;732	struct saa7164_port *p = NULL;733	int ret = -EINVAL;734	u32 std = 0;735 736	dprintk(DBGLVL_API, "%s(nr=%d type=%d)\n", __func__,737		port->nr, port->type);738 739	if (port->type == SAA7164_MPEG_ENCODER) {740		/* Pick any analog standard to init the diff.741		 * we'll come back during encoder_init'742		 * and set the correct standard if required.743		 */744		std = V4L2_STD_NTSC;745	} else746	if (port->type == SAA7164_MPEG_DVB) {747		if (port->nr == SAA7164_PORT_TS1)748			p = &dev->ports[SAA7164_PORT_ENC1];749		else750			p = &dev->ports[SAA7164_PORT_ENC2];751	} else752	if (port->type == SAA7164_MPEG_VBI) {753		std = V4L2_STD_NTSC;754		if (port->nr == SAA7164_PORT_VBI1)755			p = &dev->ports[SAA7164_PORT_ENC1];756		else757			p = &dev->ports[SAA7164_PORT_ENC2];758	} else759		BUG();760 761	if (p)762		ret = saa7164_api_configure_dif(p, std);763 764	return ret;765}766 767int saa7164_api_transition_port(struct saa7164_port *port, u8 mode)768{769	struct saa7164_dev *dev = port->dev;770 771	int ret;772 773	dprintk(DBGLVL_API, "%s(nr=%d unitid=0x%x,%d)\n",774		__func__, port->nr, port->hwcfg.unitid, mode);775 776	ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, SET_CUR,777		SAA_STATE_CONTROL, sizeof(mode), &mode);778	if (ret != SAA_OK)779		printk(KERN_ERR "%s(portnr %d unitid 0x%x) error, ret = 0x%x\n",780			__func__, port->nr, port->hwcfg.unitid, ret);781 782	return ret;783}784 785int saa7164_api_get_fw_version(struct saa7164_dev *dev, u32 *version)786{787	int ret;788 789	ret = saa7164_cmd_send(dev, 0, GET_CUR,790		GET_FW_VERSION_CONTROL, sizeof(u32), version);791	if (ret != SAA_OK)792		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);793 794	return ret;795}796 797int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen)798{799	u8 reg[] = { 0x0f, 0x00 };800 801	if (buflen < 128)802		return -ENOMEM;803 804	/* Assumption: Hauppauge eeprom is at 0xa0 on bus 0 */805	/* TODO: Pull the details from the boards struct */806	return saa7164_api_i2c_read(&dev->i2c_bus[0], 0xa0 >> 1, sizeof(reg),807		&reg[0], 128, buf);808}809 810static int saa7164_api_configure_port_vbi(struct saa7164_dev *dev,811					  struct saa7164_port *port)812{813	struct tmComResVBIFormatDescrHeader *fmt = &port->vbi_fmt_ntsc;814 815	dprintk(DBGLVL_API, "    bFormatIndex  = 0x%x\n", fmt->bFormatIndex);816	dprintk(DBGLVL_API, "    VideoStandard = 0x%x\n", fmt->VideoStandard);817	dprintk(DBGLVL_API, "    StartLine     = %d\n", fmt->StartLine);818	dprintk(DBGLVL_API, "    EndLine       = %d\n", fmt->EndLine);819	dprintk(DBGLVL_API, "    FieldRate     = %d\n", fmt->FieldRate);820	dprintk(DBGLVL_API, "    bNumLines     = %d\n", fmt->bNumLines);821 822	/* Cache the hardware configuration in the port */823 824	port->bufcounter = port->hwcfg.BARLocation;825	port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));826	port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));827	port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));828	port->bufptr32l = port->hwcfg.BARLocation +829		(4 * sizeof(u32)) +830		(sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);831	port->bufptr32h = port->hwcfg.BARLocation +832		(4 * sizeof(u32)) +833		(sizeof(u32) * port->hwcfg.buffercount);834	port->bufptr64 = port->hwcfg.BARLocation +835		(4 * sizeof(u32)) +836		(sizeof(u32) * port->hwcfg.buffercount);837	dprintk(DBGLVL_API, "   = port->hwcfg.BARLocation = 0x%x\n",838		port->hwcfg.BARLocation);839 840	dprintk(DBGLVL_API, "   = VS_FORMAT_VBI (becomes dev->en[%d])\n",841		port->nr);842 843	return 0;844}845 846static int847saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,848				   struct saa7164_port *port,849				   struct tmComResTSFormatDescrHeader *tsfmt)850{851	dprintk(DBGLVL_API, "    bFormatIndex = 0x%x\n", tsfmt->bFormatIndex);852	dprintk(DBGLVL_API, "    bDataOffset  = 0x%x\n", tsfmt->bDataOffset);853	dprintk(DBGLVL_API, "    bPacketLength= 0x%x\n", tsfmt->bPacketLength);854	dprintk(DBGLVL_API, "    bStrideLength= 0x%x\n", tsfmt->bStrideLength);855	dprintk(DBGLVL_API, "    bguid        = (....)\n");856 857	/* Cache the hardware configuration in the port */858 859	port->bufcounter = port->hwcfg.BARLocation;860	port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));861	port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));862	port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));863	port->bufptr32l = port->hwcfg.BARLocation +864		(4 * sizeof(u32)) +865		(sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);866	port->bufptr32h = port->hwcfg.BARLocation +867		(4 * sizeof(u32)) +868		(sizeof(u32) * port->hwcfg.buffercount);869	port->bufptr64 = port->hwcfg.BARLocation +870		(4 * sizeof(u32)) +871		(sizeof(u32) * port->hwcfg.buffercount);872	dprintk(DBGLVL_API, "   = port->hwcfg.BARLocation = 0x%x\n",873		port->hwcfg.BARLocation);874 875	dprintk(DBGLVL_API, "   = VS_FORMAT_MPEGTS (becomes dev->ts[%d])\n",876		port->nr);877 878	return 0;879}880 881static int882saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev,883				   struct saa7164_port *port,884				   struct tmComResPSFormatDescrHeader *fmt)885{886	dprintk(DBGLVL_API, "    bFormatIndex = 0x%x\n", fmt->bFormatIndex);887	dprintk(DBGLVL_API, "    wPacketLength= 0x%x\n", fmt->wPacketLength);888	dprintk(DBGLVL_API, "    wPackLength=   0x%x\n", fmt->wPackLength);889	dprintk(DBGLVL_API, "    bPackDataType= 0x%x\n", fmt->bPackDataType);890 891	/* Cache the hardware configuration in the port */892	/* TODO: CHECK THIS in the port config */893	port->bufcounter = port->hwcfg.BARLocation;894	port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));895	port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));896	port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));897	port->bufptr32l = port->hwcfg.BARLocation +898		(4 * sizeof(u32)) +899		(sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);900	port->bufptr32h = port->hwcfg.BARLocation +901		(4 * sizeof(u32)) +902		(sizeof(u32) * port->hwcfg.buffercount);903	port->bufptr64 = port->hwcfg.BARLocation +904		(4 * sizeof(u32)) +905		(sizeof(u32) * port->hwcfg.buffercount);906	dprintk(DBGLVL_API, "   = port->hwcfg.BARLocation = 0x%x\n",907		port->hwcfg.BARLocation);908 909	dprintk(DBGLVL_API, "   = VS_FORMAT_MPEGPS (becomes dev->enc[%d])\n",910		port->nr);911 912	return 0;913}914 915static int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)916{917	struct saa7164_port *tsport = NULL;918	struct saa7164_port *encport = NULL;919	struct saa7164_port *vbiport = NULL;920	u32 idx, next_offset;921	int i;922	struct tmComResDescrHeader *hdr, *t;923	struct tmComResExtDevDescrHeader *exthdr;924	struct tmComResPathDescrHeader *pathhdr;925	struct tmComResAntTermDescrHeader *anttermhdr;926	struct tmComResTunerDescrHeader *tunerunithdr;927	struct tmComResDMATermDescrHeader *vcoutputtermhdr;928	struct tmComResTSFormatDescrHeader *tsfmt;929	struct tmComResPSFormatDescrHeader *psfmt;930	struct tmComResSelDescrHeader *psel;931	struct tmComResProcDescrHeader *pdh;932	struct tmComResAFeatureDescrHeader *afd;933	struct tmComResEncoderDescrHeader *edh;934	struct tmComResVBIFormatDescrHeader *vbifmt;935	u32 currpath = 0;936 937	dprintk(DBGLVL_API,938		"%s(?,?,%d) sizeof(struct tmComResDescrHeader) = %d bytes\n",939		__func__, len, (u32)sizeof(struct tmComResDescrHeader));940 941	for (idx = 0; idx < (len - sizeof(struct tmComResDescrHeader));) {942 943		hdr = (struct tmComResDescrHeader *)(buf + idx);944 945		if (hdr->type != CS_INTERFACE)946			return SAA_ERR_NOT_SUPPORTED;947 948		dprintk(DBGLVL_API, "@ 0x%x =\n", idx);949		switch (hdr->subtype) {950		case GENERAL_REQUEST:951			dprintk(DBGLVL_API, " GENERAL_REQUEST\n");952			break;953		case VC_TUNER_PATH:954			dprintk(DBGLVL_API, " VC_TUNER_PATH\n");955			pathhdr = (struct tmComResPathDescrHeader *)(buf + idx);956			dprintk(DBGLVL_API, "  pathid = 0x%x\n",957				pathhdr->pathid);958			currpath = pathhdr->pathid;959			break;960		case VC_INPUT_TERMINAL:961			dprintk(DBGLVL_API, " VC_INPUT_TERMINAL\n");962			anttermhdr =963				(struct tmComResAntTermDescrHeader *)(buf + idx);964			dprintk(DBGLVL_API, "  terminalid   = 0x%x\n",965				anttermhdr->terminalid);966			dprintk(DBGLVL_API, "  terminaltype = 0x%x\n",967				anttermhdr->terminaltype);968			switch (anttermhdr->terminaltype) {969			case ITT_ANTENNA:970				dprintk(DBGLVL_API, "   = ITT_ANTENNA\n");971				break;972			case LINE_CONNECTOR:973				dprintk(DBGLVL_API, "   = LINE_CONNECTOR\n");974				break;975			case SPDIF_CONNECTOR:976				dprintk(DBGLVL_API, "   = SPDIF_CONNECTOR\n");977				break;978			case COMPOSITE_CONNECTOR:979				dprintk(DBGLVL_API,980					"   = COMPOSITE_CONNECTOR\n");981				break;982			case SVIDEO_CONNECTOR:983				dprintk(DBGLVL_API, "   = SVIDEO_CONNECTOR\n");984				break;985			case COMPONENT_CONNECTOR:986				dprintk(DBGLVL_API,987					"   = COMPONENT_CONNECTOR\n");988				break;989			case STANDARD_DMA:990				dprintk(DBGLVL_API, "   = STANDARD_DMA\n");991				break;992			default:993				dprintk(DBGLVL_API, "   = undefined (0x%x)\n",994					anttermhdr->terminaltype);995			}996			dprintk(DBGLVL_API, "  assocterminal= 0x%x\n",997				anttermhdr->assocterminal);998			dprintk(DBGLVL_API, "  iterminal    = 0x%x\n",999				anttermhdr->iterminal);1000			dprintk(DBGLVL_API, "  controlsize  = 0x%x\n",1001				anttermhdr->controlsize);1002			break;1003		case VC_OUTPUT_TERMINAL:1004			dprintk(DBGLVL_API, " VC_OUTPUT_TERMINAL\n");1005			vcoutputtermhdr =1006				(struct tmComResDMATermDescrHeader *)(buf + idx);1007			dprintk(DBGLVL_API, "  unitid = 0x%x\n",1008				vcoutputtermhdr->unitid);1009			dprintk(DBGLVL_API, "  terminaltype = 0x%x\n",1010				vcoutputtermhdr->terminaltype);1011			switch (vcoutputtermhdr->terminaltype) {1012			case ITT_ANTENNA:1013				dprintk(DBGLVL_API, "   = ITT_ANTENNA\n");1014				break;1015			case LINE_CONNECTOR:1016				dprintk(DBGLVL_API, "   = LINE_CONNECTOR\n");1017				break;1018			case SPDIF_CONNECTOR:1019				dprintk(DBGLVL_API, "   = SPDIF_CONNECTOR\n");1020				break;1021			case COMPOSITE_CONNECTOR:1022				dprintk(DBGLVL_API,1023					"   = COMPOSITE_CONNECTOR\n");1024				break;1025			case SVIDEO_CONNECTOR:1026				dprintk(DBGLVL_API, "   = SVIDEO_CONNECTOR\n");1027				break;1028			case COMPONENT_CONNECTOR:1029				dprintk(DBGLVL_API,1030					"   = COMPONENT_CONNECTOR\n");1031				break;1032			case STANDARD_DMA:1033				dprintk(DBGLVL_API, "   = STANDARD_DMA\n");1034				break;1035			default:1036				dprintk(DBGLVL_API, "   = undefined (0x%x)\n",1037					vcoutputtermhdr->terminaltype);1038			}1039			dprintk(DBGLVL_API, "  assocterminal= 0x%x\n",1040				vcoutputtermhdr->assocterminal);1041			dprintk(DBGLVL_API, "  sourceid     = 0x%x\n",1042				vcoutputtermhdr->sourceid);1043			dprintk(DBGLVL_API, "  iterminal    = 0x%x\n",1044				vcoutputtermhdr->iterminal);1045			dprintk(DBGLVL_API, "  BARLocation  = 0x%x\n",1046				vcoutputtermhdr->BARLocation);1047			dprintk(DBGLVL_API, "  flags        = 0x%x\n",1048				vcoutputtermhdr->flags);1049			dprintk(DBGLVL_API, "  interruptid  = 0x%x\n",1050				vcoutputtermhdr->interruptid);1051			dprintk(DBGLVL_API, "  buffercount  = 0x%x\n",1052				vcoutputtermhdr->buffercount);1053			dprintk(DBGLVL_API, "  metadatasize = 0x%x\n",1054				vcoutputtermhdr->metadatasize);1055			dprintk(DBGLVL_API, "  controlsize  = 0x%x\n",1056				vcoutputtermhdr->controlsize);1057			dprintk(DBGLVL_API, "  numformats   = 0x%x\n",1058				vcoutputtermhdr->numformats);1059 1060			next_offset = idx + (vcoutputtermhdr->len);1061			for (i = 0; i < vcoutputtermhdr->numformats; i++) {1062				t = (struct tmComResDescrHeader *)1063					(buf + next_offset);1064				switch (t->subtype) {1065				case VS_FORMAT_MPEG2TS:1066					tsfmt =1067					(struct tmComResTSFormatDescrHeader *)t;1068					if (currpath == 1)1069						tsport = &dev->ports[SAA7164_PORT_TS1];1070					else1071						tsport = &dev->ports[SAA7164_PORT_TS2];1072					memcpy(&tsport->hwcfg, vcoutputtermhdr,1073						sizeof(*vcoutputtermhdr));1074					saa7164_api_configure_port_mpeg2ts(dev,1075						tsport, tsfmt);1076					break;1077				case VS_FORMAT_MPEG2PS:1078					psfmt =1079					(struct tmComResPSFormatDescrHeader *)t;1080					if (currpath == 1)1081						encport = &dev->ports[SAA7164_PORT_ENC1];1082					else1083						encport = &dev->ports[SAA7164_PORT_ENC2];1084					memcpy(&encport->hwcfg, vcoutputtermhdr,1085						sizeof(*vcoutputtermhdr));1086					saa7164_api_configure_port_mpeg2ps(dev,1087						encport, psfmt);1088					break;1089				case VS_FORMAT_VBI:1090					vbifmt =1091					(struct tmComResVBIFormatDescrHeader *)t;1092					if (currpath == 1)1093						vbiport = &dev->ports[SAA7164_PORT_VBI1];1094					else1095						vbiport = &dev->ports[SAA7164_PORT_VBI2];1096					memcpy(&vbiport->hwcfg, vcoutputtermhdr,1097						sizeof(*vcoutputtermhdr));1098					memcpy(&vbiport->vbi_fmt_ntsc, vbifmt,1099						sizeof(*vbifmt));1100					saa7164_api_configure_port_vbi(dev,1101						vbiport);1102					break;1103				case VS_FORMAT_RDS:1104					dprintk(DBGLVL_API,1105						"   = VS_FORMAT_RDS\n");1106					break;1107				case VS_FORMAT_UNCOMPRESSED:1108					dprintk(DBGLVL_API,1109					"   = VS_FORMAT_UNCOMPRESSED\n");1110					break;1111				case VS_FORMAT_TYPE:1112					dprintk(DBGLVL_API,1113						"   = VS_FORMAT_TYPE\n");1114					break;1115				default:1116					dprintk(DBGLVL_API,1117						"   = undefined (0x%x)\n",1118						t->subtype);1119				}1120				next_offset += t->len;1121			}1122 1123			break;1124		case TUNER_UNIT:1125			dprintk(DBGLVL_API, " TUNER_UNIT\n");1126			tunerunithdr =1127				(struct tmComResTunerDescrHeader *)(buf + idx);1128			dprintk(DBGLVL_API, "  unitid = 0x%x\n",1129				tunerunithdr->unitid);1130			dprintk(DBGLVL_API, "  sourceid = 0x%x\n",1131				tunerunithdr->sourceid);1132			dprintk(DBGLVL_API, "  iunit = 0x%x\n",1133				tunerunithdr->iunit);1134			dprintk(DBGLVL_API, "  tuningstandards = 0x%x\n",1135				tunerunithdr->tuningstandards);1136			dprintk(DBGLVL_API, "  controlsize = 0x%x\n",1137				tunerunithdr->controlsize);1138			dprintk(DBGLVL_API, "  controls = 0x%x\n",1139				tunerunithdr->controls);1140 1141			if (tunerunithdr->unitid == tunerunithdr->iunit) {1142				if (currpath == 1)1143					encport = &dev->ports[SAA7164_PORT_ENC1];1144				else1145					encport = &dev->ports[SAA7164_PORT_ENC2];1146				memcpy(&encport->tunerunit, tunerunithdr,1147					sizeof(struct tmComResTunerDescrHeader));1148				dprintk(DBGLVL_API,1149					"  (becomes dev->enc[%d] tuner)\n",1150					encport->nr);1151			}1152			break;1153		case VC_SELECTOR_UNIT:1154			psel = (struct tmComResSelDescrHeader *)(buf + idx);1155			dprintk(DBGLVL_API, " VC_SELECTOR_UNIT\n");1156			dprintk(DBGLVL_API, "  unitid = 0x%x\n",1157				psel->unitid);1158			dprintk(DBGLVL_API, "  nrinpins = 0x%x\n",1159				psel->nrinpins);1160			dprintk(DBGLVL_API, "  sourceid = 0x%x\n",1161				psel->sourceid);1162			break;1163		case VC_PROCESSING_UNIT:1164			pdh = (struct tmComResProcDescrHeader *)(buf + idx);1165			dprintk(DBGLVL_API, " VC_PROCESSING_UNIT\n");1166			dprintk(DBGLVL_API, "  unitid = 0x%x\n",1167				pdh->unitid);1168			dprintk(DBGLVL_API, "  sourceid = 0x%x\n",1169				pdh->sourceid);1170			dprintk(DBGLVL_API, "  controlsize = 0x%x\n",1171				pdh->controlsize);1172			if (pdh->controlsize == 0x04) {1173				if (currpath == 1)1174					encport = &dev->ports[SAA7164_PORT_ENC1];1175				else1176					encport = &dev->ports[SAA7164_PORT_ENC2];1177				memcpy(&encport->vidproc, pdh,1178					sizeof(struct tmComResProcDescrHeader));1179				dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n",1180					encport->nr);1181			}1182			break;1183		case FEATURE_UNIT:1184			afd = (struct tmComResAFeatureDescrHeader *)(buf + idx);1185			dprintk(DBGLVL_API, " FEATURE_UNIT\n");1186			dprintk(DBGLVL_API, "  unitid = 0x%x\n",1187				afd->unitid);1188			dprintk(DBGLVL_API, "  sourceid = 0x%x\n",1189				afd->sourceid);1190			dprintk(DBGLVL_API, "  controlsize = 0x%x\n",1191				afd->controlsize);1192			if (currpath == 1)1193				encport = &dev->ports[SAA7164_PORT_ENC1];1194			else1195				encport = &dev->ports[SAA7164_PORT_ENC2];1196			memcpy(&encport->audfeat, afd,1197				sizeof(struct tmComResAFeatureDescrHeader));1198			dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n",1199				encport->nr);1200			break;1201		case ENCODER_UNIT:1202			edh = (struct tmComResEncoderDescrHeader *)(buf + idx);1203			dprintk(DBGLVL_API, " ENCODER_UNIT\n");1204			dprintk(DBGLVL_API, "  subtype = 0x%x\n", edh->subtype);1205			dprintk(DBGLVL_API, "  unitid = 0x%x\n", edh->unitid);1206			dprintk(DBGLVL_API, "  vsourceid = 0x%x\n",1207			edh->vsourceid);1208			dprintk(DBGLVL_API, "  asourceid = 0x%x\n",1209				edh->asourceid);1210			dprintk(DBGLVL_API, "  iunit = 0x%x\n", edh->iunit);1211			if (edh->iunit == edh->unitid) {1212				if (currpath == 1)1213					encport = &dev->ports[SAA7164_PORT_ENC1];1214				else1215					encport = &dev->ports[SAA7164_PORT_ENC2];1216				memcpy(&encport->encunit, edh,1217					sizeof(struct tmComResEncoderDescrHeader));1218				dprintk(DBGLVL_API,1219					"  (becomes dev->enc[%d])\n",1220					encport->nr);1221			}1222			break;1223		case EXTENSION_UNIT:1224			dprintk(DBGLVL_API, " EXTENSION_UNIT\n");1225			exthdr = (struct tmComResExtDevDescrHeader *)(buf + idx);1226			dprintk(DBGLVL_API, "  unitid = 0x%x\n",1227				exthdr->unitid);1228			dprintk(DBGLVL_API, "  deviceid = 0x%x\n",1229				exthdr->deviceid);1230			dprintk(DBGLVL_API, "  devicetype = 0x%x\n",1231				exthdr->devicetype);1232			if (exthdr->devicetype & 0x1)1233				dprintk(DBGLVL_API, "   = Decoder Device\n");1234			if (exthdr->devicetype & 0x2)1235				dprintk(DBGLVL_API, "   = GPIO Source\n");1236			if (exthdr->devicetype & 0x4)1237				dprintk(DBGLVL_API, "   = Video Decoder\n");1238			if (exthdr->devicetype & 0x8)1239				dprintk(DBGLVL_API, "   = Audio Decoder\n");1240			if (exthdr->devicetype & 0x20)1241				dprintk(DBGLVL_API, "   = Crossbar\n");1242			if (exthdr->devicetype & 0x40)1243				dprintk(DBGLVL_API, "   = Tuner\n");1244			if (exthdr->devicetype & 0x80)1245				dprintk(DBGLVL_API, "   = IF PLL\n");1246			if (exthdr->devicetype & 0x100)1247				dprintk(DBGLVL_API, "   = Demodulator\n");1248			if (exthdr->devicetype & 0x200)1249				dprintk(DBGLVL_API, "   = RDS Decoder\n");1250			if (exthdr->devicetype & 0x400)1251				dprintk(DBGLVL_API, "   = Encoder\n");1252			if (exthdr->devicetype & 0x800)1253				dprintk(DBGLVL_API, "   = IR Decoder\n");1254			if (exthdr->devicetype & 0x1000)1255				dprintk(DBGLVL_API, "   = EEPROM\n");1256			if (exthdr->devicetype & 0x2000)1257				dprintk(DBGLVL_API,1258					"   = VBI Decoder\n");1259			if (exthdr->devicetype & 0x10000)1260				dprintk(DBGLVL_API,1261					"   = Streaming Device\n");1262			if (exthdr->devicetype & 0x20000)1263				dprintk(DBGLVL_API,1264					"   = DRM Device\n");1265			if (exthdr->devicetype & 0x40000000)1266				dprintk(DBGLVL_API,1267					"   = Generic Device\n");1268			if (exthdr->devicetype & 0x80000000)1269				dprintk(DBGLVL_API,1270					"   = Config Space Device\n");1271			dprintk(DBGLVL_API, "  numgpiopins = 0x%x\n",1272				exthdr->numgpiopins);1273			dprintk(DBGLVL_API, "  numgpiogroups = 0x%x\n",1274				exthdr->numgpiogroups);1275			dprintk(DBGLVL_API, "  controlsize = 0x%x\n",1276				exthdr->controlsize);1277			if (exthdr->devicetype & 0x80) {1278				if (currpath == 1)1279					encport = &dev->ports[SAA7164_PORT_ENC1];1280				else1281					encport = &dev->ports[SAA7164_PORT_ENC2];1282				memcpy(&encport->ifunit, exthdr,1283					sizeof(struct tmComResExtDevDescrHeader));1284				dprintk(DBGLVL_API,1285					"  (becomes dev->enc[%d])\n",1286					encport->nr);1287			}1288			break;1289		case PVC_INFRARED_UNIT:1290			dprintk(DBGLVL_API, " PVC_INFRARED_UNIT\n");1291			break;1292		case DRM_UNIT:1293			dprintk(DBGLVL_API, " DRM_UNIT\n");1294			break;1295		default:1296			dprintk(DBGLVL_API, "default %d\n", hdr->subtype);1297		}1298 1299		dprintk(DBGLVL_API, " 1.%x\n", hdr->len);1300		dprintk(DBGLVL_API, " 2.%x\n", hdr->type);1301		dprintk(DBGLVL_API, " 3.%x\n", hdr->subtype);1302		dprintk(DBGLVL_API, " 4.%x\n", hdr->unitid);1303 1304		idx += hdr->len;1305	}1306 1307	return 0;1308}1309 1310int saa7164_api_enum_subdevs(struct saa7164_dev *dev)1311{1312	int ret;1313	u32 buflen = 0;1314	u8 *buf;1315 1316	dprintk(DBGLVL_API, "%s()\n", __func__);1317 1318	/* Get the total descriptor length */1319	ret = saa7164_cmd_send(dev, 0, GET_LEN,1320		GET_DESCRIPTORS_CONTROL, sizeof(buflen), &buflen);1321	if (ret != SAA_OK)1322		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);1323 1324	dprintk(DBGLVL_API, "%s() total descriptor size = %d bytes.\n",1325		__func__, buflen);1326 1327	/* Allocate enough storage for all of the descs */1328	buf = kzalloc(buflen, GFP_KERNEL);1329	if (!buf)1330		return SAA_ERR_NO_RESOURCES;1331 1332	/* Retrieve them */1333	ret = saa7164_cmd_send(dev, 0, GET_CUR,1334		GET_DESCRIPTORS_CONTROL, buflen, buf);1335	if (ret != SAA_OK) {1336		printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);1337		goto out;1338	}1339 1340	if (saa_debug & DBGLVL_API)1341		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf,1342			       buflen & ~15, false);1343 1344	saa7164_api_dump_subdevs(dev, buf, buflen);1345 1346out:1347	kfree(buf);1348	return ret;1349}1350 1351int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg,1352	u32 datalen, u8 *data)1353{1354	struct saa7164_dev *dev = bus->dev;1355	u16 len = 0;1356	int unitid;1357	u8 buf[256];1358	int ret;1359 1360	dprintk(DBGLVL_API, "%s() addr=%x reglen=%d datalen=%d\n",1361		__func__, addr, reglen, datalen);1362 1363	if (reglen > 4)1364		return -EIO;1365 1366	/* Prepare the send buffer */1367	/* Bytes 00-03 source register length1368	 *       04-07 source bytes to read1369	 *       08... register address1370	 */1371	memset(buf, 0, sizeof(buf));1372	memcpy((buf + 2 * sizeof(u32) + 0), reg, reglen);1373	*((u32 *)(buf + 0 * sizeof(u32))) = reglen;1374	*((u32 *)(buf + 1 * sizeof(u32))) = datalen;1375 1376	unitid = saa7164_i2caddr_to_unitid(bus, addr);1377	if (unitid < 0) {1378		printk(KERN_ERR1379			"%s() error, cannot translate regaddr 0x%x to unitid\n",1380			__func__, addr);1381		return -EIO;1382	}1383 1384	ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN,1385		EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);1386	if (ret != SAA_OK) {1387		printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);1388		return -EIO;1389	}1390 1391	dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);1392 1393	if (saa_debug & DBGLVL_I2C)1394		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf,1395			       32, false);1396 1397	ret = saa7164_cmd_send(bus->dev, unitid, GET_CUR,1398		EXU_REGISTER_ACCESS_CONTROL, len, &buf);1399	if (ret != SAA_OK)1400		printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);1401	else {1402		if (saa_debug & DBGLVL_I2C)1403			print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,1404				       buf, sizeof(buf), false);1405		memcpy(data, (buf + 2 * sizeof(u32) + reglen), datalen);1406	}1407 1408	return ret == SAA_OK ? 0 : -EIO;1409}1410 1411/* For a given 8 bit i2c address device, write the buffer */1412int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen,1413	u8 *data)1414{1415	struct saa7164_dev *dev = bus->dev;1416	u16 len = 0;1417	int unitid;1418	int reglen;1419	u8 buf[256];1420	int ret;1421 1422	dprintk(DBGLVL_API, "%s() addr=0x%2x len=0x%x\n",1423		__func__, addr, datalen);1424 1425	if ((datalen == 0) || (datalen > 232))1426		return -EIO;1427 1428	memset(buf, 0, sizeof(buf));1429 1430	unitid = saa7164_i2caddr_to_unitid(bus, addr);1431	if (unitid < 0) {1432		printk(KERN_ERR1433			"%s() error, cannot translate regaddr 0x%x to unitid\n",1434			__func__, addr);1435		return -EIO;1436	}1437 1438	reglen = saa7164_i2caddr_to_reglen(bus, addr);1439	if (reglen < 0) {1440		printk(KERN_ERR1441			"%s() error, cannot translate regaddr to reglen\n",1442			__func__);1443		return -EIO;1444	}1445 1446	ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN,1447		EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);1448	if (ret != SAA_OK) {1449		printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);1450		return -EIO;1451	}1452 1453	dprintk(DBGLVL_API, "%s() len = %d bytes unitid=0x%x\n", __func__,1454		len, unitid);1455 1456	/* Prepare the send buffer */1457	/* Bytes 00-03 dest register length1458	 *       04-07 dest bytes to write1459	 *       08... register address1460	 */1461	*((u32 *)(buf + 0 * sizeof(u32))) = reglen;1462	*((u32 *)(buf + 1 * sizeof(u32))) = datalen - reglen;1463	memcpy((buf + 2 * sizeof(u32)), data, datalen);1464 1465	if (saa_debug & DBGLVL_I2C)1466		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,1467			       buf, sizeof(buf), false);1468 1469	ret = saa7164_cmd_send(bus->dev, unitid, SET_CUR,1470		EXU_REGISTER_ACCESS_CONTROL, len, &buf);1471	if (ret != SAA_OK)1472		printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);1473 1474	return ret == SAA_OK ? 0 : -EIO;1475}1476 1477static int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid,1478	u8 pin, u8 state)1479{1480	int ret;1481	struct tmComResGPIO t;1482 1483	dprintk(DBGLVL_API, "%s(0x%x, %d, %d)\n",1484		__func__, unitid, pin, state);1485 1486	if ((pin > 7) || (state > 2))1487		return SAA_ERR_BAD_PARAMETER;1488 1489	t.pin = pin;1490	t.state = state;1491 1492	ret = saa7164_cmd_send(dev, unitid, SET_CUR,1493		EXU_GPIO_CONTROL, sizeof(t), &t);1494	if (ret != SAA_OK)1495		printk(KERN_ERR "%s() error, ret = 0x%x\n",1496			__func__, ret);1497 1498	return ret;1499}1500 1501int saa7164_api_set_gpiobit(struct saa7164_dev *dev, u8 unitid,1502	u8 pin)1503{1504	return saa7164_api_modify_gpio(dev, unitid, pin, 1);1505}1506 1507int saa7164_api_clear_gpiobit(struct saa7164_dev *dev, u8 unitid,1508	u8 pin)1509{1510	return saa7164_api_modify_gpio(dev, unitid, pin, 0);1511}1512 1513