예제 #1
0
/* We rely on a table held in the firmware - Quick check. */
int ivtv_yuv_filter_check(struct ivtv *itv)
{
	int i, offset_y, offset_uv;

	for (i=0, offset_y = 16, offset_uv = 4; i<16; i++, offset_y += 24, offset_uv += 12) {
		if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + offset_y) != i << 16) ||
		    (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + offset_uv) != i << 16)) {
			IVTV_WARN ("YUV filter table not found in firmware.\n");
			return -1;
		}
	}
	return 0;
}
예제 #2
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]);
	}
}
예제 #3
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;
}
예제 #4
0
static int ivtv_open(struct file *filp)
{
	struct video_device *vdev = video_devdata(filp);
	struct ivtv_stream *s = video_get_drvdata(vdev);
	struct ivtv *itv = s->itv;
	struct ivtv_open_id *item;
	int res = 0;

	IVTV_DEBUG_FILE("open %s\n", s->name);

	if (ivtv_init_on_first_open(itv)) {
		IVTV_ERR("Failed to initialize on device %s\n",
			 video_device_node_name(vdev));
		return -ENXIO;
	}

#ifdef CONFIG_VIDEO_ADV_DEBUG
	/* Unless ivtv_fw_debug is set, error out if firmware dead. */
	if (ivtv_fw_debug) {
		IVTV_WARN("Opening %s with dead firmware lockout disabled\n",
			  video_device_node_name(vdev));
		IVTV_WARN("Selected firmware errors will be ignored\n");
	} else {
#else
	if (1) {
#endif
		res = ivtv_firmware_check(itv, "ivtv_serialized_open");
		if (res == -EAGAIN)
			res = ivtv_firmware_check(itv, "ivtv_serialized_open");
		if (res < 0)
			return -EIO;
	}

	if (s->type == IVTV_DEC_STREAM_TYPE_MPG &&
		test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags))
		return -EBUSY;

	if (s->type == IVTV_DEC_STREAM_TYPE_YUV &&
		test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags))
		return -EBUSY;

	if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
		if (read_reg(0x82c) == 0) {
			IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n");
			/* return -ENODEV; */
		}
		ivtv_udma_alloc(itv);
	}

	/* Allocate memory */
	item = kzalloc(sizeof(struct ivtv_open_id), GFP_KERNEL);
	if (NULL == item) {
		IVTV_DEBUG_WARN("nomem on v4l2 open\n");
		return -ENOMEM;
	}
	v4l2_fh_init(&item->fh, &s->vdev);
	item->itv = itv;
	item->type = s->type;

	filp->private_data = &item->fh;
	v4l2_fh_add(&item->fh);

	if (item->type == IVTV_ENC_STREAM_TYPE_RAD &&
			v4l2_fh_is_singular_file(filp)) {
		if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
			if (atomic_read(&itv->capturing) > 0) {
				/* switching to radio while capture is
				   in progress is not polite */
				v4l2_fh_del(&item->fh);
				v4l2_fh_exit(&item->fh);
				kfree(item);
				return -EBUSY;
			}
		}
		/* Mark that the radio is being used. */
		set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
		/* We have the radio */
		ivtv_mute(itv);
		/* Switch tuner to radio */
		ivtv_call_all(itv, tuner, s_radio);
		/* Select the correct audio input (i.e. radio tuner) */
		ivtv_audio_set_io(itv);
		if (itv->hw_flags & IVTV_HW_SAA711X) {
			ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq,
				SAA7115_FREQ_32_11_MHZ, SAA7115_FREQ_FL_APLL);
		}
		/* Done! Unmute and continue. */
		ivtv_unmute(itv);
	}

	/* YUV or MPG Decoding Mode? */
	if (s->type == IVTV_DEC_STREAM_TYPE_MPG) {
		clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
	} else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
		set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
		/* For yuv, we need to know the dma size before we start */
		itv->dma_data_req_size =
				1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
		itv->yuv_info.stream_size = 0;
	}
	return 0;
}

int ivtv_v4l2_open(struct file *filp)
{
	struct video_device *vdev = video_devdata(filp);
	int res;

	if (mutex_lock_interruptible(vdev->lock))
		return -ERESTARTSYS;
	res = ivtv_open(filp);
	mutex_unlock(vdev->lock);
	return res;
}

void ivtv_mute(struct ivtv *itv)
{
	if (atomic_read(&itv->capturing))
		ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 1);
	IVTV_DEBUG_INFO("Mute\n");
}

void ivtv_unmute(struct ivtv *itv)
{
	if (atomic_read(&itv->capturing)) {
		ivtv_msleep_timeout(100, 0);
		ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
		ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0);
	}
	IVTV_DEBUG_INFO("Unmute\n");
}
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;
}
예제 #6
0
파일: ivtv-mailbox.c 프로젝트: 274914765/C
static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
{
    struct ivtv_mailbox_data *mbdata = (cmd >= 128) ? &itv->enc_mbox : &itv->dec_mbox;
    volatile struct ivtv_mailbox __iomem *mbox;
    int api_timeout = msecs_to_jiffies(1000);
    int flags, mb, i;
    unsigned long then;

    /* sanity checks */
    if (NULL == mbdata) {
        IVTV_ERR("No mailbox allocated\n");
        return -ENODEV;
    }
    if (args < 0 || args > CX2341X_MBOX_MAX_DATA ||
        cmd < 0 || cmd > 255 || api_info[cmd].name == NULL) {
        IVTV_ERR("Invalid MB call: cmd = 0x%02x, args = %d\n", cmd, args);
        return -EINVAL;
    }

    if (api_info[cmd].flags & API_HIGH_VOL) {
        IVTV_DEBUG_HI_MB("MB Call: %s\n", api_info[cmd].name);
    }
    else {
        IVTV_DEBUG_MB("MB Call: %s\n", api_info[cmd].name);
    }

    /* clear possibly uninitialized part of data array */
    for (i = args; i < CX2341X_MBOX_MAX_DATA; i++)
        data[i] = 0;

    /* If this command was issued within the last 30 minutes and with identical
       data, then just return 0 as there is no need to issue this command again.
       Just an optimization to prevent unnecessary use of mailboxes. */
    if (itv->api_cache[cmd].last_jiffies &&
        time_before(jiffies,
            itv->api_cache[cmd].last_jiffies +
            msecs_to_jiffies(1800000)) &&
        !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) {
        itv->api_cache[cmd].last_jiffies = jiffies;
        return 0;
    }

    flags = api_info[cmd].flags;

    if (flags & API_DMA) {
        for (i = 0; i < 100; i++) {
            mb = i % (mbdata->max_mbox + 1);
            if (try_mailbox(itv, mbdata, mb)) {
                write_mailbox(&mbdata->mbox[mb], cmd, args, data);
                clear_bit(mb, &mbdata->busy);
                return 0;
            }
            IVTV_DEBUG_WARN("%s: mailbox %d not free %08x\n",
                    api_info[cmd].name, mb, readl(&mbdata->mbox[mb].flags));
        }
        IVTV_WARN("Could not find free DMA mailbox for %s\n", api_info[cmd].name);
        clear_all_mailboxes(itv, mbdata);
        return -EBUSY;
    }

    if ((flags & API_FAST_RESULT) == API_FAST_RESULT)
        api_timeout = msecs_to_jiffies(100);

    mb = get_mailbox(itv, mbdata, flags);
    if (mb < 0) {
        IVTV_DEBUG_WARN("No free mailbox found (%s)\n", api_info[cmd].name);
        clear_all_mailboxes(itv, mbdata);
        return -EBUSY;
    }
    mbox = &mbdata->mbox[mb];
    write_mailbox(mbox, cmd, args, data);
    if (flags & API_CACHE) {
        memcpy(itv->api_cache[cmd].data, data, sizeof(itv->api_cache[cmd].data));
        itv->api_cache[cmd].last_jiffies = jiffies;
    }
    if ((flags & API_RESULT) == 0) {
        clear_bit(mb, &mbdata->busy);
        return 0;
    }

    /* Get results */
    then = jiffies;

    if (!(flags & API_NO_POLL)) {
        /* First try to poll, then switch to delays */
        for (i = 0; i < 100; i++) {
            if (readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)
                break;
        }
    }
    while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) {
        if (time_after(jiffies, then + api_timeout)) {
            IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name);
            /* reset the mailbox, but it is likely too late already */
            write_sync(0, &mbox->flags);
            clear_bit(mb, &mbdata->busy);
            return -EIO;
        }
        if (flags & API_NO_WAIT_RES)
            mdelay(1);
        else
            ivtv_msleep_timeout(1, 0);
    }
    if (time_after(jiffies, then + msecs_to_jiffies(100)))
        IVTV_DEBUG_WARN("%s took %u jiffies\n",
                api_info[cmd].name,
                jiffies_to_msecs(jiffies - then));

    for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++)
        data[i] = readl(&mbox->data[i]);
    write_sync(0, &mbox->flags);
    clear_bit(mb, &mbdata->busy);
    return 0;
}