linux/drivers/media/usb/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 via a firmware"
 298                                " reload and re-initialization; concern"
 299                                " is only warranted if this happens repeatedly"
 300                                " and rapidly.");
 301                        break;
 302                }
 303                wrData[0] = 0x7;
 304                for (idx = 0; idx < arg_cnt_recv; idx++) {
 305                        argp[idx] = rdData[idx+4];
 306                }
 307
 308                wrData[0] = 0x0;
 309                ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
 310                if (ret) break;
 311
 312        } while(0); LOCK_GIVE(hdw->ctl_lock);
 313
 314        return ret;
 315}
 316
 317
 318static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
 319                             int args, ...)
 320{
 321        va_list vl;
 322        unsigned int idx;
 323        u32 data[12];
 324
 325        if (args > ARRAY_SIZE(data)) {
 326                pvr2_trace(
 327                        PVR2_TRACE_ERROR_LEGS,
 328                        "Failed to write cx23416 command"
 329                        " - too many arguments"
 330                        " (was given %u limit %lu)",
 331                        args, (long unsigned) ARRAY_SIZE(data));
 332                return -EINVAL;
 333        }
 334
 335        va_start(vl, args);
 336        for (idx = 0; idx < args; idx++) {
 337                data[idx] = va_arg(vl, u32);
 338        }
 339        va_end(vl);
 340
 341        return pvr2_encoder_cmd(hdw,cmd,args,0,data);
 342}
 343
 344
 345/* This implements some extra setup for the encoder that seems to be
 346   specific to the PVR USB2 hardware. */
 347static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
 348{
 349        int ret = 0;
 350        int encMisc3Arg = 0;
 351
 352#if 0
 353        /* This inexplicable bit happens in the Hauppauge windows
 354           driver (for both 24xxx and 29xxx devices).  However I
 355           currently see no difference in behavior with or without
 356           this stuff.  Leave this here as a note of its existence,
 357           but don't use it. */
 358        LOCK_TAKE(hdw->ctl_lock); do {
 359                u32 dat[1];
 360                dat[0] = 0x80000640;
 361                pvr2_encoder_write_words(hdw,0x01fe,dat,1);
 362                pvr2_encoder_write_words(hdw,0x023e,dat,1);
 363        } while(0); LOCK_GIVE(hdw->ctl_lock);
 364#endif
 365
 366        /* Mike Isely <isely@pobox.com> 26-Jan-2006 The windows driver
 367           sends the following list of ENC_MISC commands (for both
 368           24xxx and 29xxx devices).  Meanings are not entirely clear,
 369           however without the ENC_MISC(3,1) command then we risk
 370           random perpetual video corruption whenever the video input
 371           breaks up for a moment (like when switching channels). */
 372
 373
 374#if 0
 375        /* This ENC_MISC(5,0) command seems to hurt 29xxx sync
 376           performance on channel changes, but is not a problem on
 377           24xxx devices. */
 378        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0);
 379#endif
 380
 381        /* This ENC_MISC(3,encMisc3Arg) command is critical - without
 382           it there will eventually be video corruption.  Also, the
 383           saa7115 case is strange - the Windows driver is passing 1
 384           regardless of device type but if we have 1 for saa7115
 385           devices the video turns sluggish.  */
 386        if (hdw->hdw_desc->flag_has_cx25840) {
 387                encMisc3Arg = 1;
 388        } else {
 389                encMisc3Arg = 0;
 390        }
 391        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,
 392                                 encMisc3Arg,0,0);
 393
 394        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
 395
 396#if 0
 397        /* This ENC_MISC(4,1) command is poisonous, so it is commented
 398           out.  But I'm leaving it here anyway to document its
 399           existence in the Windows driver.  The effect of this
 400           command is that apps displaying the stream become sluggish
 401           with stuttering video. */
 402        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0);
 403#endif
 404
 405        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
 406        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
 407
 408        /* prevent the PTSs from slowly drifting away in the generated
 409           MPEG stream */
 410        ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1);
 411
 412        return ret;
 413}
 414
 415int pvr2_encoder_adjust(struct pvr2_hdw *hdw)
 416{
 417        int ret;
 418        ret = cx2341x_update(hdw,pvr2_encoder_cmd,
 419                             (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL),
 420                             &hdw->enc_ctl_state);
 421        if (ret) {
 422                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 423                           "Error from cx2341x module code=%d",ret);
 424        } else {
 425                hdw->enc_cur_state = hdw->enc_ctl_state;
 426                hdw->enc_cur_valid = !0;
 427        }
 428        return ret;
 429}
 430
 431
 432int pvr2_encoder_configure(struct pvr2_hdw *hdw)
 433{
 434        int ret;
 435        int val;
 436        pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
 437                   " (cx2341x module)");
 438        hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
 439        hdw->enc_ctl_state.width = hdw->res_hor_val;
 440        hdw->enc_ctl_state.height = hdw->res_ver_val;
 441        hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ?
 442                                      0 : 1);
 443
 444        ret = 0;
 445
 446        ret |= pvr2_encoder_prep_config(hdw);
 447
 448        /* saa7115: 0xf0 */
 449        val = 0xf0;
 450        if (hdw->hdw_desc->flag_has_cx25840) {
 451                /* ivtv cx25840: 0x140 */
 452                val = 0x140;
 453        }
 454
 455        if (!ret) ret = pvr2_encoder_vcmd(
 456                hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
 457                val, val);
 458
 459        /* setup firmware to notify us about some events (don't know why...) */
 460        if (!ret) ret = pvr2_encoder_vcmd(
 461                hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
 462                0, 0, 0x10000000, 0xffffffff);
 463
 464        if (!ret) ret = pvr2_encoder_vcmd(
 465                hdw,CX2341X_ENC_SET_VBI_LINE, 5,
 466                0xffffffff,0,0,0,0);
 467
 468        if (ret) {
 469                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 470                           "Failed to configure cx23416");
 471                return ret;
 472        }
 473
 474        ret = pvr2_encoder_adjust(hdw);
 475        if (ret) return ret;
 476
 477        ret = pvr2_encoder_vcmd(
 478                hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
 479
 480        if (ret) {
 481                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 482                           "Failed to initialize cx23416 video input");
 483                return ret;
 484        }
 485
 486        return 0;
 487}
 488
 489
 490int pvr2_encoder_start(struct pvr2_hdw *hdw)
 491{
 492        int status;
 493
 494        /* unmask some interrupts */
 495        pvr2_write_register(hdw, 0x0048, 0xbfffffff);
 496
 497        pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
 498                          hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
 499
 500        switch (hdw->active_stream_type) {
 501        case pvr2_config_vbi:
 502                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 503                                           0x01,0x14);
 504                break;
 505        case pvr2_config_mpeg:
 506                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 507                                           0,0x13);
 508                break;
 509        default: /* Unhandled cases for now */
 510                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 511                                           0,0x13);
 512                break;
 513        }
 514        return status;
 515}
 516
 517int pvr2_encoder_stop(struct pvr2_hdw *hdw)
 518{
 519        int status;
 520
 521        /* mask all interrupts */
 522        pvr2_write_register(hdw, 0x0048, 0xffffffff);
 523
 524        switch (hdw->active_stream_type) {
 525        case pvr2_config_vbi:
 526                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 527                                           0x01,0x01,0x14);
 528                break;
 529        case pvr2_config_mpeg:
 530                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 531                                           0x01,0,0x13);
 532                break;
 533        default: /* Unhandled cases for now */
 534                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 535                                           0x01,0,0x13);
 536                break;
 537        }
 538
 539        return status;
 540}
 541