static int load_fw_direct(const char *fn, volatile u8 __iomem *mem, struct ivtv *itv, long size) { const struct firmware *fw = NULL; int retries = 3; retry: if (retries && request_firmware(&fw, fn, &itv->pdev->dev) == 0) { int i; volatile u32 __iomem *dst = (volatile u32 __iomem *)mem; const u32 *src = (const u32 *)fw->data; if (fw->size != size) { /* Due to race conditions in firmware loading (esp. with udev <0.95) the wrong file was sometimes loaded. So we check filesizes to see if at least the right-sized file was loaded. If not, then we retry. */ IVTV_INFO("Retry: file loaded was not %s (expected size %ld, got %zd)\n", fn, size, fw->size); release_firmware(fw); retries--; goto retry; } for (i = 0; i < fw->size; i += 4) { /* no need for endianness conversion on the ppc */ __raw_writel(*src, dst); dst++; src++; } IVTV_INFO("Loaded %s firmware (%zd bytes)\n", fn, fw->size); release_firmware(fw); return size; } IVTV_ERR("Unable to open firmware %s (must be %ld bytes)\n", fn, size); IVTV_ERR("Did you put the firmware in the hotplug firmware directory?\n"); return -ENOMEM; }
static int load_fw_direct(const char *fn, volatile u8 __iomem *mem, struct ivtv *itv, long size) { const struct firmware *fw = NULL; int retries = 3; retry: if (retries && request_firmware(&fw, fn, &itv->pdev->dev) == 0) { int i; volatile u32 __iomem *dst = (volatile u32 __iomem *)mem; const u32 *src = (const u32 *)fw->data; if (fw->size != size) { /* */ IVTV_INFO("Retry: file loaded was not %s (expected size %ld, got %zd)\n", fn, size, fw->size); release_firmware(fw); retries--; goto retry; } for (i = 0; i < fw->size; i += 4) { /* */ __raw_writel(*src, dst); dst++; src++; } IVTV_INFO("Loaded %s firmware (%zd bytes)\n", fn, fw->size); release_firmware(fw); return size; } IVTV_ERR("Unable to open firmware %s (must be %ld bytes)\n", fn, size); IVTV_ERR("Did you put the firmware in the hotplug firmware directory?\n"); return -ENOMEM; }
static int ivtv_reg_dev(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; int vfl_type = ivtv_stream_info[type].vfl_type; const char *name; int num; if (s->vdev == NULL) return 0; num = s->vdev->num; /* card number + user defined offset + device offset */ if (type != IVTV_ENC_STREAM_TYPE_MPG) { struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG]; if (s_mpg->vdev) num = s_mpg->vdev->num + ivtv_stream_info[type].num_offset; } video_set_drvdata(s->vdev, s); /* Register device. First try the desired minor, then any free one. */ if (video_register_device_no_warn(s->vdev, vfl_type, num)) { IVTV_ERR("Couldn't register v4l2 device for %s (device node number %d)\n", s->name, num); video_device_release(s->vdev); s->vdev = NULL; return -ENOMEM; } name = video_device_node_name(s->vdev); switch (vfl_type) { case VFL_TYPE_GRABBER: IVTV_INFO("Registered device %s for %s (%d kB)\n", name, s->name, itv->options.kilobytes[type]); break; case VFL_TYPE_RADIO: IVTV_INFO("Registered device %s for %s\n", name, s->name); break; case VFL_TYPE_VBI: if (itv->options.kilobytes[type]) IVTV_INFO("Registered device %s for %s (%d kB)\n", name, s->name, itv->options.kilobytes[type]); else IVTV_INFO("Registered device %s for %s\n", name, s->name); break; } return 0; }
void ivtv_firmware_versions(struct ivtv *itv) { u32 data[CX2341X_MBOX_MAX_DATA]; /* Encoder */ ivtv_vapi_result(itv, data, CX2341X_ENC_GET_VERSION, 0); IVTV_INFO("Encoder revision: 0x%08x\n", data[0]); if (data[0] != 0x02060039) IVTV_WARN("Recommended firmware version is 0x02060039.\n"); if (itv->has_cx23415) { /* Decoder */ ivtv_vapi_result(itv, data, CX2341X_DEC_GET_VERSION, 0); IVTV_INFO("Decoder revision: 0x%08x\n", data[0]); } }
static int subdev_log_status(struct v4l2_subdev *sd) { struct ivtv *itv = sd_to_ivtv(sd); IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT), read_reg(IVTV_REG_GPIO_IN)); return 0; }
static int subdev_log_status(struct v4l2_subdev *sd) { struct ivtv *itv = sd_to_ivtv(sd); IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT), read_reg(IVTV_REG_GPIO_IN)); v4l2_ctrl_handler_log_status(&itv->hdl_gpio, sd->name); return 0; }
static int ivtv_prep_dev(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; int num_offset = ivtv_stream_info[type].num_offset; int num = itv->instance + ivtv_first_minor + num_offset; /* These four fields are always initialized. If vdev == NULL, then this stream is not in use. In that case no other fields but these four can be used. */ s->vdev = NULL; s->itv = itv; s->type = type; s->name = ivtv_stream_info[type].name; /* Check whether the radio is supported */ if (type == IVTV_ENC_STREAM_TYPE_RAD && !(itv->v4l2_cap & V4L2_CAP_RADIO)) return 0; if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return 0; /* User explicitly selected 0 buffers for these streams, so don't create them. */ if (ivtv_stream_info[type].dma != PCI_DMA_NONE && itv->options.kilobytes[type] == 0) { IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name); return 0; } ivtv_stream_init(itv, type); /* allocate and initialize the v4l2 video device structure */ s->vdev = video_device_alloc(); if (s->vdev == NULL) { IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name); return -ENOMEM; } snprintf(s->vdev->name, sizeof(s->vdev->name), "%s %s", itv->v4l2_dev.name, s->name); s->vdev->num = num; s->vdev->v4l2_dev = &itv->v4l2_dev; s->vdev->fops = ivtv_stream_info[type].fops; s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; s->vdev->release = video_device_release; s->vdev->tvnorms = V4L2_STD_ALL; s->vdev->lock = &itv->serialize_lock; /* Locking in file operations other than ioctl should be done by the driver, not the V4L2 core. This driver needs auditing so that this flag can be removed. */ set_bit(V4L2_FL_LOCK_ALL_FOPS, &s->vdev->flags); set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); ivtv_set_funcs(s->vdev); return 0; }
static int ivtv_prep_dev(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; int num_offset = ivtv_stream_info[type].num_offset; int num = itv->instance + ivtv_first_minor + num_offset; /* */ s->vdev = NULL; s->itv = itv; s->type = type; s->name = ivtv_stream_info[type].name; /* */ if (type == IVTV_ENC_STREAM_TYPE_RAD && !(itv->v4l2_cap & V4L2_CAP_RADIO)) return 0; if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return 0; /* */ if (ivtv_stream_info[type].dma != PCI_DMA_NONE && itv->options.kilobytes[type] == 0) { IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name); return 0; } ivtv_stream_init(itv, type); /* */ s->vdev = video_device_alloc(); if (s->vdev == NULL) { IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name); return -ENOMEM; } snprintf(s->vdev->name, sizeof(s->vdev->name), "%s %s", itv->v4l2_dev.name, s->name); s->vdev->num = num; s->vdev->v4l2_dev = &itv->v4l2_dev; s->vdev->fops = ivtv_stream_info[type].fops; s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; s->vdev->release = video_device_release; s->vdev->tvnorms = V4L2_STD_ALL; s->vdev->lock = &itv->serialize_lock; set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); ivtv_set_funcs(s->vdev); return 0; }
static int ivtv_prep_dev(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; int num_offset = ivtv_stream_info[type].num_offset; int num = itv->instance + ivtv_first_minor + num_offset; /* These four fields are always initialized. If v4l2dev == NULL, then this stream is not in use. In that case no other fields but these four can be used. */ s->v4l2dev = NULL; s->itv = itv; s->type = type; s->name = ivtv_stream_info[type].name; /* Check whether the radio is supported */ if (type == IVTV_ENC_STREAM_TYPE_RAD && !(itv->v4l2_cap & V4L2_CAP_RADIO)) return 0; if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return 0; /* User explicitly selected 0 buffers for these streams, so don't create them. */ if (ivtv_stream_info[type].dma != PCI_DMA_NONE && itv->options.kilobytes[type] == 0) { IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name); return 0; } ivtv_stream_init(itv, type); /* allocate and initialize the v4l2 video device structure */ s->v4l2dev = video_device_alloc(); if (s->v4l2dev == NULL) { IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name); return -ENOMEM; } snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "%s %s", itv->device.name, s->name); s->v4l2dev->num = num; s->v4l2dev->v4l2_dev = &itv->device; s->v4l2dev->fops = ivtv_stream_info[type].fops; s->v4l2dev->release = video_device_release; s->v4l2dev->tvnorms = V4L2_STD_ALL; ivtv_set_funcs(s->v4l2dev); return 0; }
/* Check firmware running state. The checks fall through allowing multiple failures to be logged. */ int ivtv_firmware_check(struct ivtv *itv, char *where) { int res = 0; /* Check encoder is still running */ if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0) < 0) { IVTV_WARN("Encoder has died : %s\n", where); res = -1; } /* Also check audio. Only check if not in use & encoder is okay */ if (!res && !atomic_read(&itv->capturing) && (!atomic_read(&itv->decoding) || (atomic_read(&itv->decoding) < 2 && test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)))) { if (ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12) < 0) { IVTV_WARN("Audio has died (Encoder OK) : %s\n", where); res = -2; } } if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { /* Second audio check. Skip if audio already failed */ if (res != -2 && read_dec(0x100) != read_dec(0x104)) { /* Wait & try again to be certain. */ ivtv_msleep_timeout(14, 0); if (read_dec(0x100) != read_dec(0x104)) { IVTV_WARN("Audio has died (Decoder) : %s\n", where); res = -1; } } /* Check decoder is still running */ if (ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0) < 0) { IVTV_WARN("Decoder has died : %s\n", where); res = -1; } } /* If something failed & currently idle, try to reload */ if (res && !atomic_read(&itv->capturing) && !atomic_read(&itv->decoding)) { IVTV_INFO("Detected in %s that firmware had failed - " "Reloading\n", where); res = ivtv_firmware_restart(itv); /* * Even if restarted ok, still signal a problem had occurred. * The caller can come through this function again to check * if things are really ok after the restart. */ if (!res) { IVTV_INFO("Firmware restart okay\n"); res = -EAGAIN; } else { IVTV_INFO("Firmware restart failed\n"); } } else if (res) { res = -EIO; } return res; }
int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg) { struct v4l2_tuner *tuner = arg; struct v4l2_control *ctrl = arg; struct v4l2_routing *route = arg; u16 mask, data; switch (command) { case VIDIOC_INT_AUDIO_CLOCK_FREQ: mask = itv->card->gpio_audio_freq.mask; switch (*(u32 *)arg) { case 32000: data = itv->card->gpio_audio_freq.f32000; break; case 44100: data = itv->card->gpio_audio_freq.f44100; break; case 48000: default: data = itv->card->gpio_audio_freq.f48000; break; } break; case VIDIOC_G_TUNER: mask = itv->card->gpio_audio_detect.mask; if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask)) tuner->rxsubchans = V4L2_TUNER_MODE_STEREO | V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; else tuner->rxsubchans = V4L2_TUNER_SUB_MONO; return 0; case VIDIOC_S_TUNER: mask = itv->card->gpio_audio_mode.mask; switch (tuner->audmode) { case V4L2_TUNER_MODE_LANG1: data = itv->card->gpio_audio_mode.lang1; break; case V4L2_TUNER_MODE_LANG2: data = itv->card->gpio_audio_mode.lang2; break; case V4L2_TUNER_MODE_MONO: data = itv->card->gpio_audio_mode.mono; break; case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_LANG1_LANG2: default: data = itv->card->gpio_audio_mode.stereo; break; } break; case AUDC_SET_RADIO: mask = itv->card->gpio_audio_input.mask; data = itv->card->gpio_audio_input.radio; break; case VIDIOC_S_STD: mask = itv->card->gpio_audio_input.mask; data = itv->card->gpio_audio_input.tuner; break; case VIDIOC_INT_S_AUDIO_ROUTING: if (route->input > 2) return -EINVAL; mask = itv->card->gpio_audio_input.mask; switch (route->input) { case 0: data = itv->card->gpio_audio_input.tuner; break; case 1: data = itv->card->gpio_audio_input.linein; break; case 2: default: data = itv->card->gpio_audio_input.radio; break; } break; case VIDIOC_G_CTRL: if (ctrl->id != V4L2_CID_AUDIO_MUTE) return -EINVAL; mask = itv->card->gpio_audio_mute.mask; data = itv->card->gpio_audio_mute.mute; ctrl->value = (read_reg(IVTV_REG_GPIO_OUT) & mask) == data; return 0; case VIDIOC_S_CTRL: if (ctrl->id != V4L2_CID_AUDIO_MUTE) return -EINVAL; mask = itv->card->gpio_audio_mute.mask; data = ctrl->value ? itv->card->gpio_audio_mute.mute : 0; break; case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *qc = arg; if (qc->id != V4L2_CID_AUDIO_MUTE) return -EINVAL; *qc = gpio_ctrl_mute; return 0; } case VIDIOC_LOG_STATUS: IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT), read_reg(IVTV_REG_GPIO_IN)); return 0; case VIDIOC_INT_S_VIDEO_ROUTING: if (route->input > 2) /* 0:Tuner 1:Composite 2:S-Video */ return -EINVAL; mask = itv->card->gpio_video_input.mask; if (route->input == 0) data = itv->card->gpio_video_input.tuner; else if (route->input == 1) data = itv->card->gpio_video_input.composite; else data = itv->card->gpio_video_input.svideo; break; default: return -EINVAL; } if (mask) write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); return 0; }
int ivtv_firmware_check(struct ivtv *itv, char *where) { int res = 0; /* */ if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0) < 0) { IVTV_WARN("Encoder has died : %s\n", where); res = -1; } /* */ if (!res && !atomic_read(&itv->capturing) && (!atomic_read(&itv->decoding) || (atomic_read(&itv->decoding) < 2 && test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)))) { if (ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12) < 0) { IVTV_WARN("Audio has died (Encoder OK) : %s\n", where); res = -2; } } if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { /* */ if (res != -2 && read_dec(0x100) != read_dec(0x104)) { /* */ ivtv_msleep_timeout(14, 0); if (read_dec(0x100) != read_dec(0x104)) { IVTV_WARN("Audio has died (Decoder) : %s\n", where); res = -1; } } /* */ if (ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0) < 0) { IVTV_WARN("Decoder has died : %s\n", where); res = -1; } } /* */ if (res && !atomic_read(&itv->capturing) && !atomic_read(&itv->decoding)) { IVTV_INFO("Detected in %s that firmware had failed - " "Reloading\n", where); res = ivtv_firmware_restart(itv); /* */ if (!res) { IVTV_INFO("Firmware restart okay\n"); res = -EAGAIN; } else { IVTV_INFO("Firmware restart failed\n"); } } else if (res) { res = -EIO; } return res; }
static int ivtv_reg_dev(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; int vfl_type = ivtv_stream_info[type].vfl_type; int minor_offset = ivtv_stream_info[type].minor_offset; int minor; /* These four fields are always initialized. If v4l2dev == NULL, then this stream is not in use. In that case no other fields but these four can be used. */ s->v4l2dev = NULL; s->itv = itv; s->type = type; s->name = ivtv_stream_info[type].name; /* Check whether the radio is supported */ if (type == IVTV_ENC_STREAM_TYPE_RAD && !(itv->v4l2_cap & V4L2_CAP_RADIO)) return 0; if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return 0; if (minor_offset >= 0) /* card number + user defined offset + device offset */ minor = itv->num + ivtv_first_minor + minor_offset; else minor = -1; /* User explicitly selected 0 buffers for these streams, so don't create them. */ if (minor >= 0 && ivtv_stream_info[type].dma != PCI_DMA_NONE && itv->options.megabytes[type] == 0) { IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name); return 0; } ivtv_stream_init(itv, type); /* allocate and initialize the v4l2 video device structure */ s->v4l2dev = video_device_alloc(); if (s->v4l2dev == NULL) { IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name); return -ENOMEM; } s->v4l2dev->type = VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT | VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER; if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { s->v4l2dev->type |= VID_TYPE_MPEG_DECODER; } snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s", itv->num, s->name); s->v4l2dev->minor = minor; s->v4l2dev->dev = &itv->dev->dev; s->v4l2dev->fops = ivtv_stream_info[type].fops; s->v4l2dev->release = video_device_release; if (minor >= 0) { /* Register device. First try the desired minor, then any free one. */ if (video_register_device(s->v4l2dev, vfl_type, minor) && video_register_device(s->v4l2dev, vfl_type, -1)) { IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n", s->name, minor); video_device_release(s->v4l2dev); s->v4l2dev = NULL; return -ENOMEM; } } else { /* Don't register a 'hidden' stream (OSD) */ IVTV_INFO("Created framebuffer stream for %s\n", s->name); return 0; } switch (vfl_type) { case VFL_TYPE_GRABBER: IVTV_INFO("Registered device video%d for %s (%d MB)\n", s->v4l2dev->minor, s->name, itv->options.megabytes[type]); break; case VFL_TYPE_RADIO: IVTV_INFO("Registered device radio%d for %s\n", s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); break; case VFL_TYPE_VBI: if (itv->options.megabytes[type]) IVTV_INFO("Registered device vbi%d for %s (%d MB)\n", s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name, itv->options.megabytes[type]); else IVTV_INFO("Registered device vbi%d for %s\n", s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name); break; } return 0; }