linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c
<<
>>
Prefs
   1/*
   2 *
   3 *
   4 *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
   5 *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
   6 *
   7 *  This program is free software; you can redistribute it and/or modify
   8 *  it under the terms of the GNU General Public License as published by
   9 *  the Free Software Foundation; either version 2 of the License
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, write to the Free Software
  18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19 *
  20 */
  21
  22#include <linux/device.h>   // for linux/firmware.h
  23#include <linux/firmware.h>
  24#include "pvrusb2-util.h"
  25#include "pvrusb2-encoder.h"
  26#include "pvrusb2-hdw-internal.h"
  27#include "pvrusb2-debug.h"
  28#include "pvrusb2-fx2-cmd.h"
  29
  30
  31
  32/* Firmware mailbox flags - definitions found from ivtv */
  33#define IVTV_MBOX_FIRMWARE_DONE 0x00000004
  34#define IVTV_MBOX_DRIVER_DONE 0x00000002
  35#define IVTV_MBOX_DRIVER_BUSY 0x00000001
  36
  37#define MBOX_BASE 0x44
  38
  39
  40static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
  41                                    unsigned int offs,
  42                                    const u32 *data, unsigned int dlen)
  43{
  44        unsigned int idx,addr;
  45        unsigned int bAddr;
  46        int ret;
  47        unsigned int chunkCnt;
  48
  49        /*
  50
  51        Format: First byte must be 0x01.  Remaining 32 bit words are
  52        spread out into chunks of 7 bytes each, with the first 4 bytes
  53        being the data word (little endian), and the next 3 bytes
  54        being the address where that data word is to be written (big
  55        endian).  Repeat request for additional words, with offset
  56        adjusted accordingly.
  57
  58        */
  59        while (dlen) {
  60                chunkCnt = 8;
  61                if (chunkCnt > dlen) chunkCnt = dlen;
  62                memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
  63                bAddr = 0;
  64                hdw->cmd_buffer[bAddr++] = FX2CMD_MEM_WRITE_DWORD;
  65                for (idx = 0; idx < chunkCnt; idx++) {
  66                        addr = idx + offs;
  67                        hdw->cmd_buffer[bAddr+6] = (addr & 0xffu);
  68                        hdw->cmd_buffer[bAddr+5] = ((addr>>8) & 0xffu);
  69                        hdw->cmd_buffer[bAddr+4] = ((addr>>16) & 0xffu);
  70                        PVR2_DECOMPOSE_LE(hdw->cmd_buffer, bAddr,data[idx]);
  71                        bAddr += 7;
  72                }
  73                ret = pvr2_send_request(hdw,
  74                                        hdw->cmd_buffer,1+(chunkCnt*7),
  75                                        NULL,0);
  76                if (ret) return ret;
  77                data += chunkCnt;
  78                dlen -= chunkCnt;
  79                offs += chunkCnt;
  80        }
  81
  82        return 0;
  83}
  84
  85
  86static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,
  87                                   unsigned int offs,
  88                                   u32 *data, unsigned int dlen)
  89{
  90        unsigned int idx;
  91        int ret;
  92        unsigned int chunkCnt;
  93
  94        /*
  95
  96        Format: First byte must be 0x02 (status check) or 0x28 (read
  97        back block of 32 bit words).  Next 6 bytes must be zero,
  98        followed by a single byte of MBOX_BASE+offset for portion to
  99        be read.  Returned data is packed set of 32 bits words that
 100        were read.
 101
 102        */
 103
 104        while (dlen) {
 105                chunkCnt = 16;
 106                if (chunkCnt > dlen) chunkCnt = dlen;
 107                if (chunkCnt < 16) chunkCnt = 1;
 108                hdw->cmd_buffer[0] =
 109                        ((chunkCnt == 1) ?
 110                         FX2CMD_MEM_READ_DWORD : FX2CMD_MEM_READ_64BYTES);
 111                hdw->cmd_buffer[1] = 0;
 112                hdw->cmd_buffer[2] = 0;
 113                hdw->cmd_buffer[3] = 0;
 114                hdw->cmd_buffer[4] = 0;
 115                hdw->cmd_buffer[5] = ((offs>>16) & 0xffu);
 116                hdw->cmd_buffer[6] = ((offs>>8) & 0xffu);
 117                hdw->cmd_buffer[7] = (offs & 0xffu);
 118                ret = pvr2_send_request(hdw,
 119                                        hdw->cmd_buffer,8,
 120                                        hdw->cmd_buffer,
 121                                        (chunkCnt == 1 ? 4 : 16 * 4));
 122                if (ret) return ret;
 123
 124                for (idx = 0; idx < chunkCnt; idx++) {
 125                        data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4);
 126                }
 127                data += chunkCnt;
 128                dlen -= chunkCnt;
 129                offs += chunkCnt;
 130        }
 131
 132        return 0;
 133}
 134
 135
 136/* This prototype is set up to be compatible with the
 137   cx2341x_mbox_func prototype in cx2341x.h, which should be in
 138   kernels 2.6.18 or later.  We do this so that we can enable
 139   cx2341x.ko to write to our encoder (by handing it a pointer to this
 140   function).  For earlier kernels this doesn't really matter. */
 141static int pvr2_encoder_cmd(void *ctxt,
 142                            u32 cmd,
 143                            int arg_cnt_send,
 144                            int arg_cnt_recv,
 145                            u32 *argp)
 146{
 147        unsigned int poll_count;
 148        unsigned int try_count = 0;
 149        int retry_flag;
 150        int ret = 0;
 151        unsigned int idx;
 152        /* These sizes look to be limited by the FX2 firmware implementation */
 153        u32 wrData[16];
 154        u32 rdData[16];
 155        struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
 156
 157
 158        /*
 159
 160        The encoder seems to speak entirely using blocks 32 bit words.
 161        In ivtv driver terms, this is a mailbox at MBOX_BASE which we
 162        populate with data and watch what the hardware does with it.
 163        The first word is a set of flags used to control the
 164        transaction, the second word is the command to execute, the
 165        third byte is zero (ivtv driver suggests that this is some
 166        kind of return value), and the fourth byte is a specified
 167        timeout (windows driver always uses 0x00060000 except for one
 168        case when it is zero).  All successive words are the argument
 169        words for the command.
 170
 171        First, write out the entire set of words, with the first word
 172        being zero.
 173
 174        Next, write out just the first word again, but set it to
 175        IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
 176        probably means "go").
 177
 178        Next, read back the return count words.  Check the first word,
 179        which should have IVTV_MBOX_FIRMWARE_DONE set.  If however
 180        that bit is not set, then the command isn't done so repeat the
 181        read until it is set.
 182
 183        Finally, write out just the first word again, but set it to
 184        0x0 this time (which probably means "idle").
 185
 186        */
 187
 188        if (arg_cnt_send > (ARRAY_SIZE(wrData) - 4)) {
 189                pvr2_trace(
 190                        PVR2_TRACE_ERROR_LEGS,
 191                        "Failed to write cx23416 command"
 192                        " - too many input arguments"
 193                        " (was given %u limit %lu)",
 194                        arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4);
 195                return -EINVAL;
 196        }
 197
 198        if (arg_cnt_recv > (ARRAY_SIZE(rdData) - 4)) {
 199                pvr2_trace(
 200                        PVR2_TRACE_ERROR_LEGS,
 201                        "Failed to write cx23416 command"
 202                        " - too many return arguments"
 203                        " (was given %u limit %lu)",
 204                        arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4);
 205                return -EINVAL;
 206        }
 207
 208
 209        LOCK_TAKE(hdw->ctl_lock); do {
 210
 211                if (!hdw->state_encoder_ok) {
 212                        ret = -EIO;
 213                        break;
 214                }
 215
 216                retry_flag = 0;
 217                try_count++;
 218                ret = 0;
 219                wrData[0] = 0;
 220                wrData[1] = cmd;
 221                wrData[2] = 0;
 222                wrData[3] = 0x00060000;
 223                for (idx = 0; idx < arg_cnt_send; idx++) {
 224                        wrData[idx+4] = argp[idx];
 225                }
 226                for (; idx < ARRAY_SIZE(wrData) - 4; idx++) {
 227                        wrData[idx+4] = 0;
 228                }
 229
 230                ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,idx);
 231                if (ret) break;
 232                wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
 233                ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
 234                if (ret) break;
 235                poll_count = 0;
 236                while (1) {
 237                        poll_count++;
 238                        ret = pvr2_encoder_read_words(hdw,MBOX_BASE,rdData,
 239                                                      arg_cnt_recv+4);
 240                        if (ret) {
 241                                break;
 242                        }
 243                        if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
 244                                break;
 245                        }
 246                        if (rdData[0] && (poll_count < 1000)) continue;
 247                        if (!rdData[0]) {
 248                                retry_flag = !0;
 249                                pvr2_trace(
 250                                        PVR2_TRACE_ERROR_LEGS,
 251                                        "Encoder timed out waiting for us"
 252                                        "; arranging to retry");
 253                        } else {
 254                                pvr2_trace(
 255                                        PVR2_TRACE_ERROR_LEGS,
 256                                        "***WARNING*** device's encoder"
 257                                        " appears to be stuck"
 258                                        " (status=0x%08x)",rdData[0]);
 259                        }
 260                        pvr2_trace(
 261                                PVR2_TRACE_ERROR_LEGS,
 262                                "Encoder command: 0x%02x",cmd);
 263                        for (idx = 4; idx < arg_cnt_send; idx++) {
 264                                pvr2_trace(
 265                                        PVR2_TRACE_ERROR_LEGS,
 266                                        "Encoder arg%d: 0x%08x",
 267                                        idx-3,wrData[idx]);
 268                        }
 269                        ret = -EBUSY;
 270                        break;
 271                }
 272                if (retry_flag) {
 273                        if (try_count < 20) continue;
 274                        pvr2_trace(
 275                                PVR2_TRACE_ERROR_LEGS,
 276                                "Too many retries...");
 277                        ret = -EBUSY;
 278                }
 279                if (ret) {
 280                        del_timer_sync(&hdw->encoder_run_timer);
 281                        hdw->state_encoder_ok = 0;
 282                        pvr2_trace(PVR2_TRACE_STBITS,
 283                                   "State bit %s <-- %s",
 284                                   "state_encoder_ok",
 285                                   (hdw->state_encoder_ok ? "true" : "false"));
 286                        if (hdw->state_encoder_runok) {
 287                                hdw->state_encoder_runok = 0;
 288                                pvr2_trace(PVR2_TRACE_STBITS,
 289                                   "State bit %s <-- %s",
 290                                           "state_encoder_runok",
 291                                           (hdw->state_encoder_runok ?
 292                                            "true" : "false"));
 293                        }
 294                        pvr2_trace(
 295                                PVR2_TRACE_ERROR_LEGS,
 296                                "Giving up on command."
 297                                "  This is normally recovered by the driver.");
 298                        break;
 299                }
 300                wrData[0] = 0x7;
 301                for (idx = 0; idx < arg_cnt_recv; idx++) {
 302                        argp[idx] = rdData[idx+4];
 303                }
 304
 305                wrData[0] = 0x0;
 306                ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
 307                if (ret) break;
 308
 309        } while(0); LOCK_GIVE(hdw->ctl_lock);
 310
 311        return ret;
 312}
 313
 314
 315static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
 316                             int args, ...)
 317{
 318        va_list vl;
 319        unsigned int idx;
 320        u32 data[12];
 321
 322        if (args > ARRAY_SIZE(data)) {
 323                pvr2_trace(
 324                        PVR2_TRACE_ERROR_LEGS,
 325                        "Failed to write cx23416 command"
 326                        " - too many arguments"
 327                        " (was given %u limit %lu)",
 328                        args, (long unsigned) ARRAY_SIZE(data));
 329                return -EINVAL;
 330        }
 331
 332        va_start(vl, args);
 333        for (idx = 0; idx < args; idx++) {
 334                data[idx] = va_arg(vl, u32);
 335        }
 336        va_end(vl);
 337
 338        return pvr2_encoder_cmd(hdw,cmd,args,0,data);
 339}
 340
 341
 342/* This implements some extra setup for the encoder that seems to be
 343   specific to the PVR USB2 hardware. */
 344static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
 345{
 346        int ret = 0;
 347        int encMisc3Arg = 0;
 348
 349#if 0
 350        /* This inexplicable bit happens in the Hauppauge windows
 351           driver (for both 24xxx and 29xxx devices).  However I
 352           currently see no difference in behavior with or without
 353           this stuff.  Leave this here as a note of its existence,
 354           but don't use it. */
 355        LOCK_TAKE(hdw->ctl_lock); do {
 356                u32 dat[1];
 357                dat[0] = 0x80000640;
 358                pvr2_encoder_write_words(hdw,0x01fe,dat,1);
 359                pvr2_encoder_write_words(hdw,0x023e,dat,1);
 360        } while(0); LOCK_GIVE(hdw->ctl_lock);
 361#endif
 362
 363        /* Mike Isely <isely@pobox.com> 26-Jan-2006 The windows driver
 364           sends the following list of ENC_MISC commands (for both
 365           24xxx and 29xxx devices).  Meanings are not entirely clear,
 366           however without the ENC_MISC(3,1) command then we risk
 367           random perpetual video corruption whenever the video input
 368           breaks up for a moment (like when switching channels). */
 369
 370
 371#if 0
 372        /* This ENC_MISC(5,0) command seems to hurt 29xxx sync
 373           performance on channel changes, but is not a problem on
 374           24xxx devices. */
 375        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0);
 376#endif
 377
 378        /* This ENC_MISC(3,encMisc3Arg) command is critical - without
 379           it there will eventually be video corruption.  Also, the
 380           saa7115 case is strange - the Windows driver is passing 1
 381           regardless of device type but if we have 1 for saa7115
 382           devices the video turns sluggish.  */
 383        if (hdw->hdw_desc->flag_has_cx25840) {
 384                encMisc3Arg = 1;
 385        } else {
 386                encMisc3Arg = 0;
 387        }
 388        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,
 389                                 encMisc3Arg,0,0);
 390
 391        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
 392
 393#if 0
 394        /* This ENC_MISC(4,1) command is poisonous, so it is commented
 395           out.  But I'm leaving it here anyway to document its
 396           existence in the Windows driver.  The effect of this
 397           command is that apps displaying the stream become sluggish
 398           with stuttering video. */
 399        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0);
 400#endif
 401
 402        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
 403        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
 404
 405        /* prevent the PTSs from slowly drifting away in the generated
 406           MPEG stream */
 407        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1);
 408
 409        return ret;
 410}
 411
 412int pvr2_encoder_adjust(struct pvr2_hdw *hdw)
 413{
 414        int ret;
 415        ret = cx2341x_update(hdw,pvr2_encoder_cmd,
 416                             (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL),
 417                             &hdw->enc_ctl_state);
 418        if (ret) {
 419                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 420                           "Error from cx2341x module code=%d",ret);
 421        } else {
 422                memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state,
 423                       sizeof(struct cx2341x_mpeg_params));
 424                hdw->enc_cur_valid = !0;
 425        }
 426        return ret;
 427}
 428
 429
 430int pvr2_encoder_configure(struct pvr2_hdw *hdw)
 431{
 432        int ret;
 433        int val;
 434        pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
 435                   " (cx2341x module)");
 436        hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
 437        hdw->enc_ctl_state.width = hdw->res_hor_val;
 438        hdw->enc_ctl_state.height = hdw->res_ver_val;
 439        hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ?
 440                                      0 : 1);
 441
 442        ret = 0;
 443
 444        ret |= pvr2_encoder_prep_config(hdw);
 445
 446        /* saa7115: 0xf0 */
 447        val = 0xf0;
 448        if (hdw->hdw_desc->flag_has_cx25840) {
 449                /* ivtv cx25840: 0x140 */
 450                val = 0x140;
 451        }
 452
 453        if (!ret) ret = pvr2_encoder_vcmd(
 454                hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
 455                val, val);
 456
 457        /* setup firmware to notify us about some events (don't know why...) */
 458        if (!ret) ret = pvr2_encoder_vcmd(
 459                hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
 460                0, 0, 0x10000000, 0xffffffff);
 461
 462        if (!ret) ret = pvr2_encoder_vcmd(
 463                hdw,CX2341X_ENC_SET_VBI_LINE, 5,
 464                0xffffffff,0,0,0,0);
 465
 466        if (ret) {
 467                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 468                           "Failed to configure cx23416");
 469                return ret;
 470        }
 471
 472        ret = pvr2_encoder_adjust(hdw);
 473        if (ret) return ret;
 474
 475        ret = pvr2_encoder_vcmd(
 476                hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
 477
 478        if (ret) {
 479                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 480                           "Failed to initialize cx23416 video input");
 481                return ret;
 482        }
 483
 484        return 0;
 485}
 486
 487
 488int pvr2_encoder_start(struct pvr2_hdw *hdw)
 489{
 490        int status;
 491
 492        /* unmask some interrupts */
 493        pvr2_write_register(hdw, 0x0048, 0xbfffffff);
 494
 495        pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
 496                          hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
 497
 498        switch (hdw->active_stream_type) {
 499        case pvr2_config_vbi:
 500                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 501                                           0x01,0x14);
 502                break;
 503        case pvr2_config_mpeg:
 504                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 505                                           0,0x13);
 506                break;
 507        default: /* Unhandled cases for now */
 508                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 509                                           0,0x13);
 510                break;
 511        }
 512        return status;
 513}
 514
 515int pvr2_encoder_stop(struct pvr2_hdw *hdw)
 516{
 517        int status;
 518
 519        /* mask all interrupts */
 520        pvr2_write_register(hdw, 0x0048, 0xffffffff);
 521
 522        switch (hdw->active_stream_type) {
 523        case pvr2_config_vbi:
 524                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 525                                           0x01,0x01,0x14);
 526                break;
 527        case pvr2_config_mpeg:
 528                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 529                                           0x01,0,0x13);
 530                break;
 531        default: /* Unhandled cases for now */
 532                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 533                                           0x01,0,0x13);
 534                break;
 535        }
 536
 537        return status;
 538}
 539
 540
 541/*
 542  Stuff for Emacs to see, in order to encourage consistent editing style:
 543  *** Local Variables: ***
 544  *** mode: c ***
 545  *** fill-column: 70 ***
 546  *** tab-width: 8 ***
 547  *** c-basic-offset: 8 ***
 548  *** End: ***
 549  */
 550
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.