int hdmi_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
    struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
    struct device *dev = hdev->dev;
    int ret = 0;

    dev_dbg(dev, "%s start\n", __func__);

    switch (ctrl->id) {
    case V4L2_CID_TV_SET_DVI_MODE:
        hdev->dvi_mode = ctrl->value;
        break;
    case V4L2_CID_TV_SET_ASPECT_RATIO:
        hdev->aspect = ctrl->value;
        break;
    case V4L2_CID_TV_ENABLE_HDMI_AUDIO:
        mutex_lock(&hdev->mutex);
        hdev->audio_enable = !!ctrl->value;
        if (is_hdmi_streaming(hdev)) {
            hdmi_set_infoframe(hdev);
            hdmi_audio_enable(hdev, hdev->audio_enable);
        }
        mutex_unlock(&hdev->mutex);
        break;
    case V4L2_CID_TV_SET_NUM_CHANNELS:
        mutex_lock(&hdev->mutex);
        hdmi_audio_information(hdev, ctrl->value);
        if (is_hdmi_streaming(hdev)) {
            hdmi_audio_enable(hdev, 0);
            hdmi_set_infoframe(hdev);
            hdmi_reg_i2s_audio_init(hdev);
            hdmi_audio_enable(hdev, 1);
        }
        mutex_unlock(&hdev->mutex);
        break;
    case V4L2_CID_TV_SET_COLOR_RANGE:
        hdev->color_range = ctrl->value;
        break;
    case V4L2_CID_TV_HDCP_ENABLE:
        hdev->hdcp_info.hdcp_enable = ctrl->value;
        dev_dbg(hdev->dev, "HDCP %s\n",
                ctrl->value ? "enable" : "disable");
#ifdef CONFIG_SEC_MHL_HDCP
        hdev->hdcp_info.hdcp_enable = false;
        /*MHL8240 control the HDCP*/
        dev_dbg(hdev->dev, "MHL control the HDCP\n");
#endif
        break;
    default:
        dev_err(dev, "invalid control id\n");
        ret = -EINVAL;
        break;
    }

    return ret;
}
static int hdmi_streamoff(struct hdmi_device *hdev)
{
    struct device *dev = hdev->dev;

    dev_dbg(dev, "%s\n", __func__);

    if (hdev->hdcp_info.hdcp_enable && hdev->hdcp_info.hdcp_start)
        hdcp_stop(hdev);

    hdmi_audio_enable(hdev, 0);
    hdmi_enable(hdev, 0);
    hdmi_tg_enable(hdev, 0);

    hdev->streaming = HDMI_STOP;

    /* change the HPD interrupt: Internal -> External */
    disable_irq(hdev->int_irq);
    cancel_work_sync(&hdev->hpd_work);
    hdmi_reg_set_ext_hpd(hdev);
    enable_irq(hdev->ext_irq);
    dev_info(hdev->dev, "HDMI interrupt changed to external\n");

    hdmi_dumpregs(hdev, "streamoff");
    return 0;
}
Пример #3
0
static int hdmi_streamoff(struct hdmi_device *hdev)
{
	struct device *dev = hdev->dev;
	struct hdmi_resources *res = &hdev->res;

	dev_dbg(dev, "%s\n", __func__);

	if (hdev->hdcp_info.hdcp_enable)
		hdcp_stop(hdev);

	hdmi_audio_enable(hdev, 0);
	hdmi_enable(hdev, 0);
	hdmi_tg_enable(hdev, 0);

	/* pixel(vpll) clock is used for HDMI in config mode */
	clk_disable(res->sclk_hdmi);
	clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
	clk_enable(res->sclk_hdmi);

	v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0);

	hdev->streaming = 0;
	hdmi_dumpregs(hdev, "streamoff");
	return 0;
}
static int hdmi_streamon(struct hdmi_device *hdev)
{
	struct device *dev = hdev->dev;
	int ret;
	u32 val0, val1, val2;

	dev_dbg(dev, "%s\n", __func__);

	/* 3D test */
	hdmi_set_infoframe(hdev);

	/* set packets for audio */
	hdmi_set_packets(hdev);

	/* init audio */
#if defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_I2S)
	hdmi_reg_i2s_audio_init(hdev);
#elif defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_SPDIF)
	hdmi_reg_spdif_audio_init(hdev);
#endif
	/* enbale HDMI audio */
	if (hdev->audio_enable)
		hdmi_audio_enable(hdev, 1);

	hdmi_set_dvi_mode(hdev);

	/* controls the pixel value limitation */
	hdmi_reg_set_limits(hdev);

	/* enable HDMI and timing generator */
	hdmi_enable(hdev, 1);
	hdmi_tg_enable(hdev, 1);

	hdev->streaming = HDMI_STREAMING;

	/* change the HPD interrupt: External -> Internal */
	disable_irq(hdev->ext_irq);
	cancel_delayed_work_sync(&hdev->hpd_work_ext);
	hdmi_reg_set_int_hpd(hdev);
	enable_irq(hdev->int_irq);
	dev_info(hdev->dev, "HDMI interrupt changed to internal\n");

	/* start HDCP if enabled */
	if (hdev->hdcp_info.hdcp_enable) {
		ret = hdcp_start(hdev);
		if (ret)
			return ret;
	}

	val0 = hdmi_read(hdev, HDMI_ACR_MCTS0);
	val1 = hdmi_read(hdev, HDMI_ACR_MCTS1);
	val2 = hdmi_read(hdev, HDMI_ACR_MCTS2);
	dev_dbg(dev, "HDMI_ACR_MCTS0 : 0x%08x\n", val0);
	dev_dbg(dev, "HDMI_ACR_MCTS1 : 0x%08x\n", val1);
	dev_dbg(dev, "HDMI_ACR_MCTS2 : 0x%08x\n", val2);

	hdmi_dumpregs(hdev, "streamon");
	return 0;
}
Пример #5
0
int hdmi_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
	struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
	struct device *dev = hdev->dev;
	int ret = 0;

	dev_dbg(dev, "%s start\n", __func__);

	switch (ctrl->id) {
	case V4L2_CID_TV_SET_DVI_MODE:
		hdev->dvi_mode = ctrl->value;
		break;
	case V4L2_CID_TV_SET_ASPECT_RATIO:
		hdev->aspect = ctrl->value;
		break;
	case V4L2_CID_TV_ENABLE_HDMI_AUDIO:
		mutex_lock(&hdev->mutex);
		hdev->audio_enable = !!ctrl->value;
		if (is_hdmi_streaming(hdev)) {
			hdmi_set_infoframe(hdev);
			hdmi_audio_enable(hdev, hdev->audio_enable);
		}
		mutex_unlock(&hdev->mutex);
		break;
	case V4L2_CID_TV_SET_NUM_CHANNELS:
		mutex_lock(&hdev->mutex);
		if ((ctrl->value == 2) || (ctrl->value == 6) ||
							(ctrl->value == 8)) {
			hdev->audio_channel_count = ctrl->value;
		} else {
			dev_err(dev, "invalid channel count\n");
			hdev->audio_channel_count = 2;
		}
		if (is_hdmi_streaming(hdev))
			hdmi_set_infoframe(hdev);
		mutex_unlock(&hdev->mutex);
		break;
	case V4L2_CID_TV_SET_COLOR_RANGE:
		hdev->color_range = ctrl->value;
		break;
	case V4L2_CID_TV_HDCP_ENABLE:
		hdev->hdcp_info.hdcp_enable = ctrl->value;
		dev_dbg(hdev->dev, "HDCP %s\n",
				ctrl->value ? "enable" : "disable");
		break;
	default:
		dev_err(dev, "invalid control id\n");
		ret = -EINVAL;
		break;
	}

	return ret;
}
int lpa_if_start(struct lpa_if *lpa_if)
{
	pr_debug("buf1 0x%x, buf2 0x%x dma_ch %d\n",
		(unsigned int)lpa_if->audio_buf[0].data,
		(unsigned int)lpa_if->audio_buf[1].data, lpa_if->dma_ch);

	dai_start_hdmi(lpa_if->dma_ch);

	hdmi_audio_enable(1, HDMI_AUDIO_FIFO_WATER_MARK);

	hdmi_audio_packet_enable(1);
	return 0;
}
Пример #7
0
static int hdmi_streamoff(struct hdmi_device *hdev)
{
	struct device *dev = hdev->dev;

	dev_dbg(dev, "%s\n", __func__);

	hdmi_reg_set_ext_hpd(hdev);

//	if (edid_supports_hdmi(hdev)) {
#if 1 
		if (hdev->hdcp_info.hdcp_enable && hdev->hdcp_info.hdcp_start)
			hdcp_stop(hdev);
#endif
//	}

	hdmi_audio_enable(hdev, 0);
	hdmi_enable(hdev, 0);
	hdmi_tg_enable(hdev, 0);

	hdev->streaming = HDMI_STOP;

	hdmi_dumpregs(hdev, "streamoff");
	return 0;
}
static ssize_t lpa_if_write(struct file *file, const char __user *buf,
		size_t count, loff_t *pos)
{
	struct lpa_if *lpa_if = file->private_data;
	struct audio_buffer *ab;
	const char __user *start = buf;
	int xfer, rc;
	struct sched_param s = { .sched_priority = 1 };
	int old_prio = current->rt_priority;
	int old_policy = current->policy;
	int cap_nice = cap_raised(current_cap(), CAP_SYS_NICE);

	 /* just for this write, set us real-time */
	if (!task_has_rt_policy(current)) {
		struct cred *new = prepare_creds();
		cap_raise(new->cap_effective, CAP_SYS_NICE);
		commit_creds(new);
		if ((sched_setscheduler(current, SCHED_RR, &s)) < 0)
			pr_err("sched_setscheduler failed\n");
	}
	mutex_lock(&lpa_if->lock);

	if (dma_buf_index < 2) {

		ab = lpa_if->audio_buf + dma_buf_index;

		if (copy_from_user(ab->data, buf, count)) {
			pr_err("copy from user failed\n");
			rc = 0;
			goto end;

		}
		mb();
		pr_debug("prefill: count %u  audio_buf[%u].size %u\n",
			 count, dma_buf_index, ab->size);

		ab->used = 1;
		dma_buf_index++;
		rc =  count;
		goto end;
	}

	if (lpa_if->config != 1) {
		pr_err("AUDIO_START did not happen\n");
		rc = 0;
		goto end;
	}

	while (count > 0) {

		ab = lpa_if->audio_buf + lpa_if->cpu_buf;

		rc = wait_event_timeout(lpa_if->wait, (ab->used == 0), 10 * HZ);
		if (!rc) {
			pr_err("wait_event_timeout failed\n");
			rc =  buf - start;
			goto end;
		}

		xfer = count;

		if (xfer > lpa_if->dma_period_sz)
			xfer = lpa_if->dma_period_sz;

		if (copy_from_user(ab->data, buf, xfer)) {
			pr_err("copy from user failed\n");
			rc = buf - start;
			goto end;
		}

		mb();
		buf += xfer;
		count -= xfer;
		ab->used = 1;

		pr_debug("xfer %d, size %d, used %d cpu_buf %d\n",
			xfer, ab->size, ab->used, lpa_if->cpu_buf);
		lpa_if->cpu_buf++;
		lpa_if->cpu_buf = lpa_if->cpu_buf % lpa_if->cfg.buffer_count;
	}
	rc = buf - start;
end:
	mutex_unlock(&lpa_if->lock);
	/* restore old scheduling policy */
	if (!rt_policy(old_policy)) {
		struct sched_param v = { .sched_priority = old_prio };
		if ((sched_setscheduler(current, old_policy, &v)) < 0)
			pr_err("sched_setscheduler failed\n");
		if (likely(!cap_nice)) {
			struct cred *new = prepare_creds();
			cap_lower(new->cap_effective, CAP_SYS_NICE);
			commit_creds(new);
		}
	}
	return rc;
}

static int lpa_if_release(struct inode *inode, struct file *file)
{
	struct lpa_if *lpa_if = file->private_data;

	hdmi_audio_packet_enable(0);

	wait_for_dma_cnt_stop(lpa_if->dma_ch);

	hdmi_audio_enable(0, HDMI_AUDIO_FIFO_WATER_MARK);

	if (lpa_if->config) {
		unregister_dma_irq_handler(lpa_if->dma_ch);
		dai_stop_hdmi(lpa_if->dma_ch);
		lpa_if->config = 0;
	}
	core_req_bus_bandwith(AUDIO_IF_BUS_ID, 0, 0);

	if (hdmi_msm_audio_get_sample_rate() != HDMI_SAMPLE_RATE_48KHZ)
		hdmi_msm_audio_sample_rate_reset(HDMI_SAMPLE_RATE_48KHZ);

	return 0;
}

static const struct file_operations lpa_if_fops = {
	.owner = THIS_MODULE,
	.open = lpa_if_open,
	.write = lpa_if_write,
	.release = lpa_if_release,
	.unlocked_ioctl = lpa_if_ioctl,
};

struct miscdevice lpa_if_misc = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = "msm_lpa_if_out",
	.fops = &lpa_if_fops,
};

static int __init lpa_if_init(void)
{
	int rc;

	lpa_if_ptr = kzalloc(sizeof(struct lpa_if), GFP_KERNEL);
	if (!lpa_if_ptr) {
		pr_info("No mem for lpa-if\n");
		return -ENOMEM;
	}

	mutex_init(&lpa_if_ptr->lock);
	init_waitqueue_head(&lpa_if_ptr->wait);

	lpa_if_ptr->buffer = dma_alloc_coherent(NULL, DMA_ALLOC_BUF_SZ,
				    &(lpa_if_ptr->buffer_phys), GFP_KERNEL);
	if (!lpa_if_ptr->buffer) {
		pr_err("dma_alloc_coherent failed\n");
		kfree(lpa_if_ptr);
		return -ENOMEM;
	}

	pr_info("lpa_if_ptr 0x%08x   buf_vir 0x%08x   buf_phy 0x%08x "
		" buf_zise %u\n", (u32)lpa_if_ptr,
		(u32)(lpa_if_ptr->buffer), lpa_if_ptr->buffer_phys,
		DMA_ALLOC_BUF_SZ);

	rc =  misc_register(&lpa_if_misc);
	if (rc < 0) {
		pr_err("misc_register failed\n");

		dma_free_coherent(NULL, DMA_ALLOC_BUF_SZ, lpa_if_ptr->buffer,
				lpa_if_ptr->buffer_phys);
		kfree(lpa_if_ptr);
	}
	return rc;
}

device_initcall(lpa_if_init);
Пример #9
0
static int hdmi_streamon(struct hdmi_device *hdev)
{
	struct device *dev = hdev->dev;
	int ret;
	u32 val0, val1, val2;

	dev_dbg(dev, "%s\n", __func__);

	/* 3D test */
	hdmi_set_infoframe(hdev);

	/* set packets for audio */
	hdmi_set_packets(hdev);

	/* init audio */
#if defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_I2S)
	//printk("=============================> HDMI IIS\n");
	hdmi_reg_i2s_audio_init(hdev);
#elif defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_SPDIF)
	hdmi_reg_spdif_audio_init(hdev);
#endif
	/* enbale HDMI audio */
	if (hdev->audio_enable)
	{
	    //printk("<+++++++++++++++++++++++++++++++++++++++++++ HDMI  ENABLE\n");
		hdmi_audio_enable(hdev, 1);
	    //printk("<+++++++++++++++++++++++++++++++++++++++++++ HDMI  ENABLE\n");
	}

	hdmi_set_dvi_mode(hdev);

	/* controls the pixel value limitation */
	hdmi_reg_set_limits(hdev);

	/* enable HDMI and timing generator */
	hdmi_enable(hdev, 1);
	hdmi_tg_enable(hdev, 1);

	hdmi_reg_set_int_hpd(hdev);

	hdev->streaming = HDMI_STREAMING;

//	if (edid_supports_hdmi(hdev)) {
#if 1 
		/* start HDCP if enabled */
		if (hdev->hdcp_info.hdcp_enable) {
			ret = hdcp_start(hdev);
			if (ret)
				return ret;
		}
#endif
//	}

	val0 = hdmi_read(hdev, HDMI_ACR_MCTS0);
	val1 = hdmi_read(hdev, HDMI_ACR_MCTS1);
	val2 = hdmi_read(hdev, HDMI_ACR_MCTS2);
	dev_dbg(dev, "HDMI_ACR_MCTS0 : 0x%08x\n", val0);
	dev_dbg(dev, "HDMI_ACR_MCTS1 : 0x%08x\n", val1);
	dev_dbg(dev, "HDMI_ACR_MCTS2 : 0x%08x\n", val2);

	hdmi_dumpregs(hdev, "streamon");
	return 0;
}
Пример #10
0
static int hdmi_streamon(struct hdmi_device *hdev)
{
	struct device *dev = hdev->dev;
	struct hdmi_resources *res = &hdev->res;
	int ret, tries;
	u32 val0, val1, val2;

	dev_dbg(dev, "%s\n", __func__);

	hdev->streaming = 1;
	ret = v4l2_subdev_call(hdev->phy_sd, video, s_stream, 1);
	if (ret)
		return ret;

	/* waiting for HDMIPHY's PLL to get to steady state */
	for (tries = 100; tries; --tries) {
		if (is_hdmiphy_ready(hdev))
			break;

		mdelay(1);
	}
	/* steady state not achieved */
	if (tries == 0) {
		dev_err(dev, "hdmiphy's pll could not reach steady state.\n");
		v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0);
		hdmi_dumpregs(hdev, "s_stream");
		return -EIO;
	}

	/* hdmiphy clock is used for HDMI in streaming mode */
	clk_disable(res->sclk_hdmi);
	clk_set_parent(res->sclk_hdmi, res->sclk_hdmiphy);
	clk_enable(res->sclk_hdmi);

	/* 3D test */
	hdmi_set_infoframe(hdev);

	/* set packets for audio */
	hdmi_set_packets(hdev);

	/* init audio */
#if defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_I2S)
	hdmi_reg_i2s_audio_init(hdev);
#elif defined(CONFIG_VIDEO_EXYNOS_HDMI_AUDIO_SPDIF)
	hdmi_reg_spdif_audio_init(hdev);
#endif
	/* enbale HDMI audio */
	if (hdev->audio_enable)
		hdmi_audio_enable(hdev, 1);

	hdmi_set_dvi_mode(hdev);

	/* enable HDMI and timing generator */
	hdmi_enable(hdev, 1);
	hdmi_tg_enable(hdev, 1);

	mdelay(5);
	val0 = hdmi_read(hdev, HDMI_ACR_MCTS0);
	val1 = hdmi_read(hdev, HDMI_ACR_MCTS1);
	val2 = hdmi_read(hdev, HDMI_ACR_MCTS2);
	dev_dbg(dev, "HDMI_ACR_MCTS0 : 0x%08x\n", val0);
	dev_dbg(dev, "HDMI_ACR_MCTS1 : 0x%08x\n", val1);
	dev_dbg(dev, "HDMI_ACR_MCTS2 : 0x%08x\n", val2);

	/* start HDCP if enabled */
	if (hdev->hdcp_info.hdcp_enable) {
		ret = hdcp_start(hdev);
		if (ret)
			return ret;
	}

	hdmi_dumpregs(hdev, "streamon");
	return 0;
}