root/drivers/media/usb/pvrusb2/pvrusb2-encoder.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pvr2_encoder_write_words
  2. pvr2_encoder_read_words
  3. pvr2_encoder_cmd
  4. pvr2_encoder_vcmd
  5. pvr2_encoder_prep_config
  6. pvr2_encoder_adjust
  7. pvr2_encoder_configure
  8. pvr2_encoder_start
  9. pvr2_encoder_stop

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

/* [<][>][^][v][top][bottom][index][help] */