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 ®[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