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 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                memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state,
 426                       sizeof(struct cx2341x_mpeg_params));
 427                hdw->enc_cur_valid = !0;
 428        }
 429        return ret;
 430}
 431
 432
 433int pvr2_encoder_configure(struct pvr2_hdw *hdw)
 434{
 435        int ret;
 436        int val;
 437        pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
 438                   " (cx2341x module)");
 439        hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
 440        hdw->enc_ctl_state.width = hdw->res_hor_val;
 441        hdw->enc_ctl_state.height = hdw->res_ver_val;
 442        hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ?
 443                                      0 : 1);
 444
 445        ret = 0;
 446
 447        ret |= pvr2_encoder_prep_config(hdw);
 448
 449        /* saa7115: 0xf0 */
 450        val = 0xf0;
 451        if (hdw->hdw_desc->flag_has_cx25840) {
 452                /* ivtv cx25840: 0x140 */
 453                val = 0x140;
 454        }
 455
 456        if (!ret) ret = pvr2_encoder_vcmd(
 457                hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
 458                val, val);
 459
 460        /* setup firmware to notify us about some events (don't know why...) */
 461        if (!ret) ret = pvr2_encoder_vcmd(
 462                hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
 463                0, 0, 0x10000000, 0xffffffff);
 464
 465        if (!ret) ret = pvr2_encoder_vcmd(
 466                hdw,CX2341X_ENC_SET_VBI_LINE, 5,
 467                0xffffffff,0,0,0,0);
 468
 469        if (ret) {
 470                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 471                           "Failed to configure cx23416");
 472                return ret;
 473        }
 474
 475        ret = pvr2_encoder_adjust(hdw);
 476        if (ret) return ret;
 477
 478        ret = pvr2_encoder_vcmd(
 479                hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
 480
 481        if (ret) {
 482                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 483                           "Failed to initialize cx23416 video input");
 484                return ret;
 485        }
 486
 487        return 0;
 488}
 489
 490
 491int pvr2_encoder_start(struct pvr2_hdw *hdw)
 492{
 493        int status;
 494
 495        /* unmask some interrupts */
 496        pvr2_write_register(hdw, 0x0048, 0xbfffffff);
 497
 498        pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
 499                          hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
 500
 501        switch (hdw->active_stream_type) {
 502        case pvr2_config_vbi:
 503                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 504                                           0x01,0x14);
 505                break;
 506        case pvr2_config_mpeg:
 507                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 508                                           0,0x13);
 509                break;
 510        default: /* Unhandled cases for now */
 511                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
 512                                           0,0x13);
 513                break;
 514        }
 515        return status;
 516}
 517
 518int pvr2_encoder_stop(struct pvr2_hdw *hdw)
 519{
 520        int status;
 521
 522        /* mask all interrupts */
 523        pvr2_write_register(hdw, 0x0048, 0xffffffff);
 524
 525        switch (hdw->active_stream_type) {
 526        case pvr2_config_vbi:
 527                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 528                                           0x01,0x01,0x14);
 529                break;
 530        case pvr2_config_mpeg:
 531                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 532                                           0x01,0,0x13);
 533                break;
 534        default: /* Unhandled cases for now */
 535                status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
 536                                           0x01,0,0x13);
 537                break;
 538        }
 539
 540        return status;
 541}
 542
 543
 544/*
 545  Stuff for Emacs to see, in order to encourage consistent editing style:
 546  *** Local Variables: ***
 547  *** mode: c ***
 548  *** fill-column: 70 ***
 549  *** tab-width: 8 ***
 550  *** c-basic-offset: 8 ***
 551  *** End: ***
 552  */
 553