示例#1
0
static irqreturn_t hdmi_tx_isr(int irq, void *data)
{
	u32 hpd_int_status;
	u32 hpd_int_ctrl;
	struct hdmi_tx_io_data *io = NULL;
	struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)data;

	if (!hdmi_ctrl || !hdmi_ctrl->hpd_initialized) {
		DEV_WARN("%s: invalid input data, ISR ignored\n", __func__);
		return IRQ_HANDLED;
	}

	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
	if (!io->base) {
		DEV_WARN("%s: io not initialized, ISR ignored\n", __func__);
		return IRQ_HANDLED;
	}

	/* Process HPD Interrupt */
	hpd_int_status = HDMI_REG_R(io->base, HDMI_HPD_INT_STATUS);
	hpd_int_ctrl = HDMI_REG_R(io->base, HDMI_HPD_INT_CTRL);
	if ((hpd_int_ctrl & BIT(2)) && (hpd_int_status & BIT(0))) {
		u32 cable_detected = hpd_int_status & BIT(1);

		/*
		 * Clear all interrupts, timer will turn IRQ back on
		 * Leaving the bit[2] on, else core goes off
		 * on getting HPD during power off.
		 */
		HDMI_REG_W(io->base, HDMI_HPD_INT_CTRL, BIT(2) | BIT(0));

		DEV_DBG("%s: HPD IRQ, Ctrl=%04x, State=%04x\n", __func__,
			hpd_int_ctrl, hpd_int_status);

		mutex_lock(&hdmi_ctrl->mutex);
		hdmi_ctrl->hpd_cable_chg_detected = true;
		hdmi_ctrl->hpd_prev_state = cable_detected ? 0 : 1;
		hdmi_ctrl->hpd_stable = 0;
		mutex_unlock(&hdmi_ctrl->mutex);

		mod_timer(&hdmi_ctrl->hpd_state_timer, jiffies + HZ/2);

		return IRQ_HANDLED;
	}

	DEV_DBG("%s: HPD<Ctrl=%04x, State=%04x>\n", __func__, hpd_int_ctrl,
		hpd_int_status);

	return IRQ_HANDLED;
} /* hdmi_tx_isr */
示例#2
0
/*
 * Write a value to a register on adv7520 device.
 * Returns zero if successful, or non-zero otherwise.
 */
static int adv7520_write_reg(struct i2c_client *client, u8 reg, u8 val)
{
	int err;
	struct i2c_msg msg[1];
	unsigned char data[2];

	if (!client->adapter)
		return -ENODEV;
	if (!atomic_read(&comm_power_on)) {
		DEV_WARN("%s: WARN: missing GPIO power\n", __func__);
		return -ENODEV;
	}

	msg->addr = client->addr;
	msg->flags = 0;
	msg->len = 2;
	msg->buf = data;
	data[0] = reg;
	data[1] = val;

	err = i2c_transfer(client->adapter, msg, 1);
	if (err >= 0)
		return 0;
#ifdef PORT_DEBUG
	DEV_INFO("HDMI[%02x] [W] %02x [%d]\n", reg, val, err);
#endif
	return err;
}
/*
 * Read a value from a register on ADV7525 device
 * If sucessfull returns value read , otherwise error.
 */
static u8 adv7525_read_reg(struct i2c_client *client, u8 reg)
{
	int err;
	struct i2c_msg msg[2];
	u8 reg_buf[] = { reg };
	u8 data_buf[] = { 0 };

	if (!client->adapter)
		return -ENODEV;
	if (!gpio_power_on) {
		DEV_WARN("%s: WARN: missing GPIO power\n", __func__);
		return -ENODEV;
	}
	msg[0].addr = client->addr;
	msg[0].flags = 0;
	msg[0].len = 1;
	msg[0].buf = reg_buf;

	msg[1].addr = client->addr;
	msg[1].flags = I2C_M_RD;
	msg[1].len = 1;
	msg[1].buf = data_buf;

	err = i2c_transfer(client->adapter, msg, 2);
	if (err < 0) {
		DEV_INFO("%s: I2C err: %d\n", __func__, err);
		return err;
	}

#ifdef PORT_DEBUG
	DEV_INFO("HDMI[%02x] [R] %02x\n", reg, data);
#endif
	return *data_buf;
}
示例#4
0
static int hdmi_tx_check_capability(void __iomem *base)
{
	u32 hdmi_disabled, hdcp_disabled;

	if (!base) {
		DEV_ERR("%s: invalid input\n", __func__);
		return -EINVAL;
	}

	/* QFPROM_RAW_FEAT_CONFIG_ROW0_LSB */
	hdcp_disabled = HDMI_REG_R_ND(base, 0x000000F8) & BIT(31);
	/* QFPROM_RAW_FEAT_CONFIG_ROW0_MSB */
	hdmi_disabled = HDMI_REG_R_ND(base, 0x000000FC) & BIT(0);

	DEV_DBG("%s: Features <HDMI:%s, HDCP:%s>\n", __func__,
		hdmi_disabled ? "OFF" : "ON", hdcp_disabled ? "OFF" : "ON");

	if (hdmi_disabled) {
		DEV_ERR("%s: HDMI disabled\n", __func__);
		return -ENODEV;
	}

	if (hdcp_disabled)
		DEV_WARN("%s: HDCP disabled\n", __func__);

	return 0;
} /* hdmi_tx_check_capability */
示例#5
0
static void adv7520_hdcp_enable(struct work_struct *work)
{
	DEV_INFO("HDCP: Start reg[0xaf]=%02x (mute audio)\n", reg[0xaf]);

	adv7520_comm_power(1, 1);

	/* Mute Audio */
	adv7520_write_reg(hclient, 0x0C, (u8)0xC3);

	msleep(200);
	/* Wait for BKSV ready interrupt */
	/* Read BKSV's keys from HDTV */
	reg[0xBF] = adv7520_read_reg(hclient, 0xBF);
	reg[0xC0] = adv7520_read_reg(hclient, 0xC0);
	reg[0xC1] = adv7520_read_reg(hclient, 0xC1);
	reg[0xC2] = adv7520_read_reg(hclient, 0xC2);
	reg[0xc3] = adv7520_read_reg(hclient, 0xC3);

	DEV_DBG("HDCP: BKSV={%02x,%02x,%02x,%02x,%02x}\n", reg[0xbf], reg[0xc0],
		reg[0xc1], reg[0xc2], reg[0xc3]);

	/* Is SINK repeater */
	reg[0xBE] = adv7520_read_reg(hclient, 0xBE);
	if (~(reg[0xBE] & 0x40)) {
		; /* compare with revocation list */
		/* Check 20 1's and 20 zero's */
	} else {
		/* Don't implement HDCP if sink as a repeater */
		adv7520_write_reg(hclient, 0x0C, (u8)0x84);
		mutex_lock(&hdcp_state_mutex);
		hdcp_activating = FALSE;
		mutex_unlock(&hdcp_state_mutex);
		DEV_WARN("HDCP: Sink Repeater (%02x), (unmute audio)\n",
			reg[0xbe]);

		adv7520_comm_power(0, 1);
		return;
	}

	msleep(200);
	reg[0xB8] = adv7520_read_reg(hclient, 0xB8);
	DEV_INFO("HDCP: Status reg[0xB8] is %02x\n", reg[0xb8]);
	if (reg[0xb8] & 0x40) {
		/* UnMute Audio */
		adv7520_write_reg(hclient, 0x0C, (u8)0x84);
		DEV_INFO("HDCP: A/V content Encrypted (unmute audio)\n");
		external_common_state->hdcp_active = TRUE;
	}
	adv7520_comm_power(0, 1);

	mutex_lock(&hdcp_state_mutex);
	hdcp_activating = FALSE;
	mutex_unlock(&hdcp_state_mutex);
}
static void adv7520_hdcp_enable(struct work_struct *work)
{
	DEV_INFO("HDCP: Start reg[0xaf]=%02x (mute audio)\n", reg[0xaf]);

	adv7520_comm_power(1, 1);

	
	adv7520_write_reg(hclient, 0x0C, (u8)0xC3);

	msleep(200);
	
	
	reg[0xBF] = adv7520_read_reg(hclient, 0xBF);
	reg[0xC0] = adv7520_read_reg(hclient, 0xC0);
	reg[0xC1] = adv7520_read_reg(hclient, 0xC1);
	reg[0xC2] = adv7520_read_reg(hclient, 0xC2);
	reg[0xc3] = adv7520_read_reg(hclient, 0xC3);

	DEV_DBG("HDCP: BKSV={%02x,%02x,%02x,%02x,%02x}\n", reg[0xbf], reg[0xc0],
		reg[0xc1], reg[0xc2], reg[0xc3]);

	
	reg[0xBE] = adv7520_read_reg(hclient, 0xBE);
	if (~(reg[0xBE] & 0x40)) {
		; 
		
	} else {
		
		adv7520_write_reg(hclient, 0x0C, (u8)0x84);
		mutex_lock(&hdcp_state_mutex);
		hdcp_activating = FALSE;
		mutex_unlock(&hdcp_state_mutex);
		DEV_WARN("HDCP: Sink Repeater (%02x), (unmute audio)\n",
			reg[0xbe]);

		adv7520_comm_power(0, 1);
		return;
	}

	msleep(200);
	reg[0xB8] = adv7520_read_reg(hclient, 0xB8);
	DEV_INFO("HDCP: Status reg[0xB8] is %02x\n", reg[0xb8]);
	if (reg[0xb8] & 0x40) {
		
		adv7520_write_reg(hclient, 0x0C, (u8)0x84);
		DEV_INFO("HDCP: A/V content Encrypted (unmute audio)\n");
		external_common_state->hdcp_active = TRUE;
	}
	adv7520_comm_power(0, 1);

	mutex_lock(&hdcp_state_mutex);
	hdcp_activating = FALSE;
	mutex_unlock(&hdcp_state_mutex);
}
/* Interrupt debounce timer */
static void tvout_msm_hpd_state_timer(unsigned long data)
{
#ifdef CONFIG_SUSPEND
	mutex_lock(&tvout_msm_state_mutex);
	if (tvout_msm_state->pm_suspended) {
		mutex_unlock(&tvout_msm_state_mutex);
		DEV_WARN("%s: ignored, pm_suspended\n", __func__);
		return;
	}
	mutex_unlock(&tvout_msm_state_mutex);
#endif

	if (tvenc_pdata->poll)
		if (!tvout_msm_state || !tvout_msm_state->disp_powered_up) {
			DEV_DBG("%s: ignored, display powered off\n", __func__);
			return;
		}

	/* TV_INTR_STATUS[0x204]
		When a TV_ENC interrupt occurs, then reading this register will
		indicate what caused the interrupt since that each bit indicates
		the source of the interrupt that had happened. If multiple
		interrupt sources had happened, then multiple bits of this
		register will be set
		Bit 0 : Load present on Video1
		Bit 1 : Load present on Video2
		Bit 2 : Load removed on Video1
		Bit 3 : Load removed on Video2
	*/

	/* Locking interrupt status is not required because
	last status read after debouncing is used */
	if ((tvout_msm_state->hpd_int_status & 0x05) == 0x05) {
		/* SW-workaround :If the status read after debouncing is
		0x05(indicating both load present & load removed- which can't
		happen in reality), force an update. If status remains 0x05
		after retry, it's a cable unplug event */
		if (++tvout_msm_state->five_retry < 2) {
			uint32 reg;
			DEV_DBG("tvout: Timer: 0x05\n");
			TV_OUT(TV_INTR_CLEAR, 0xf);
			reg = TV_IN(TV_DAC_INTF);
			TV_OUT(TV_DAC_INTF, reg & ~TVENC_LOAD_DETECT_EN);
			TV_OUT(TV_INTR_CLEAR, 0xf);
			reg = TV_IN(TV_DAC_INTF);
			TV_OUT(TV_DAC_INTF, reg | TVENC_LOAD_DETECT_EN);
			return;
		}
	}
	tvout_msm_state->five_retry = 0;
	tvout_check_status();
}
static void tvout_msm_hpd_work(struct work_struct *work)
{
	uint32 reg;

#ifdef CONFIG_SUSPEND
	mutex_lock(&tvout_msm_state_mutex);
	if (tvout_msm_state->pm_suspended) {
		mutex_unlock(&tvout_msm_state_mutex);
		DEV_WARN("%s: ignored, pm_suspended\n", __func__);
		return;
	}
	mutex_unlock(&tvout_msm_state_mutex);
#endif

	/* Enable power lines & clocks */
	tvenc_pdata->pm_vid_en(1);
	tvenc_set_clock(CLOCK_ON);

	/* Enable encoder to get a stable interrupt */
	reg = TV_IN(TV_ENC_CTL);
	TV_OUT(TV_ENC_CTL, reg | TVENC_CTL_ENC_EN);

	/* SW- workaround to update status register */
	reg = TV_IN(TV_DAC_INTF);
	TV_OUT(TV_DAC_INTF, reg & ~TVENC_LOAD_DETECT_EN);
	TV_OUT(TV_INTR_CLEAR, 0xf);
	reg = TV_IN(TV_DAC_INTF);
	TV_OUT(TV_DAC_INTF, reg | TVENC_LOAD_DETECT_EN);

	tvout_msm_state->hpd_int_status = TV_IN(TV_INTR_STATUS);

	/* Disable TV encoder */
	reg = TV_IN(TV_ENC_CTL);
	TV_OUT(TV_ENC_CTL, reg & ~TVENC_CTL_ENC_EN);

	/*Disable power lines & clocks */
	tvenc_set_clock(CLOCK_OFF);
	tvenc_pdata->pm_vid_en(0);

	DEV_DBG("%s: ISR: 0x%02x\n", __func__,
		tvout_msm_state->hpd_int_status & 0x05);

	mod_timer(&tvout_msm_state->hpd_work_timer, jiffies
		+ msecs_to_jiffies(TVOUT_HPD_DUTY_CYCLE));

	tvout_check_status();
}
示例#9
0
void CGameServer::LinkGameDBServer(void)
{
	if (m_bGameDBCnnted && (m_bGameDBLinked == false)) {
		m_ServerInfo.usStatus = STATUSU_LINK;

		CGameLink Link;
		Link.SetServerData(m_ServerInfo);
		Link.AdjustSize();

		CStreamScopePtr StreamPtr;
		m_NetworkPtr->AllocBuffer(StreamPtr);
		if (StreamPtr != nullptr) {
			Link.Serialize(*StreamPtr);
			m_ServerInfo.Addr(*StreamPtr);

			m_NetworkPtr->Send(m_krConnectGameDB, *StreamPtr);
		}
		else {
			DEV_WARN(TF("[游戏服务器]向游戏DB服务器注册时创建网络数据流异常!"));
			LOG_WARN(m_FileLog, TF("[游戏服务器]向游戏DB服务器注册时创建网络数据流异常!"));
		}
	}
}
static int tvout_on(struct platform_device *pdev)
{
	uint32 reg = 0;
	struct fb_var_screeninfo *var;
	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);

	if (!mfd)
		return -ENODEV;

	if (mfd->key != MFD_KEY)
		return -EINVAL;

#ifdef CONFIG_SUSPEND
	mutex_lock(&tvout_msm_state_mutex);
	if (tvout_msm_state->pm_suspended) {
		mutex_unlock(&tvout_msm_state_mutex);
		DEV_WARN("%s: ignored, pm_suspended\n", __func__);
		return -ENODEV;
	}
	mutex_unlock(&tvout_msm_state_mutex);
#endif

	var = &mfd->fbi->var;
	if (var->reserved[3] >= NTSC_M && var->reserved[3] <= PAL_N)
		external_common_state->video_resolution = var->reserved[3];

	tvout_msm_state->pdev = pdev;
	if (del_timer(&tvout_msm_state->hpd_work_timer))
		DEV_DBG("%s: work timer stopped\n", __func__);

	TV_OUT(TV_ENC_CTL, 0);	/* disable TV encoder */

	switch (external_common_state->video_resolution) {
	case NTSC_M:
	case NTSC_J:
		TV_OUT(TV_CGMS, 0x0);
		/*  NTSC Timing */
		TV_OUT(TV_SYNC_1, 0x0020009e);
		TV_OUT(TV_SYNC_2, 0x011306B4);
		TV_OUT(TV_SYNC_3, 0x0006000C);
		TV_OUT(TV_SYNC_4, 0x0028020D);
		TV_OUT(TV_SYNC_5, 0x005E02FB);
		TV_OUT(TV_SYNC_6, 0x0006000C);
		TV_OUT(TV_SYNC_7, 0x00000012);
		TV_OUT(TV_BURST_V1, 0x0013020D);
		TV_OUT(TV_BURST_V2, 0x0014020C);
		TV_OUT(TV_BURST_V3, 0x0013020D);
		TV_OUT(TV_BURST_V4, 0x0014020C);
		TV_OUT(TV_BURST_H, 0x00AE00F2);
		TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
		TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);

		reg |= TVENC_CTL_TV_MODE_NTSC_M_PAL60;

		if (external_common_state->video_resolution == NTSC_M) {
			/* Cr gain 11, Cb gain C6, y_gain 97 */
			TV_OUT(TV_GAIN, 0x0081B697);
		} else {
			/* Cr gain 11, Cb gain C6, y_gain 97 */
			TV_OUT(TV_GAIN, 0x008bc4a3);
			reg |= TVENC_CTL_NTSCJ_MODE;
		}

		var->yres = 480;
		break;
	case PAL_BDGHIN:
	case PAL_N:
		/*  PAL Timing */
		TV_OUT(TV_SYNC_1, 0x00180097);
		TV_OUT(TV_SYNC_3, 0x0005000a);
		TV_OUT(TV_SYNC_4, 0x00320271);
		TV_OUT(TV_SYNC_5, 0x005602f9);
		TV_OUT(TV_SYNC_6, 0x0005000a);
		TV_OUT(TV_SYNC_7, 0x0000000f);
		TV_OUT(TV_BURST_V1, 0x0012026e);
		TV_OUT(TV_BURST_V2, 0x0011026d);
		TV_OUT(TV_BURST_V3, 0x00100270);
		TV_OUT(TV_BURST_V4, 0x0013026f);
		TV_OUT(TV_SOL_REQ_ODD, 0x0030026e);
		TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f);

		if (external_common_state->video_resolution == PAL_BDGHIN) {
			/* Cr gain 11, Cb gain C6, y_gain 97 */
			TV_OUT(TV_GAIN, 0x0088c1a0);
			TV_OUT(TV_CGMS, 0x00012345);
			TV_OUT(TV_SYNC_2, 0x011f06c0);
			TV_OUT(TV_BURST_H, 0x00af00ea);
			reg |= TVENC_CTL_TV_MODE_PAL_BDGHIN;
		} else {
			/* Cr gain 11, Cb gain C6, y_gain 97 */
			TV_OUT(TV_GAIN, 0x0081b697);
			TV_OUT(TV_CGMS, 0x000af317);
			TV_OUT(TV_SYNC_2, 0x12006c0);
			TV_OUT(TV_BURST_H, 0x00af00fa);
			reg |= TVENC_CTL_TV_MODE_PAL_N;
		}
		var->yres = 576;
		break;
	case PAL_M:
		/* Cr gain 11, Cb gain C6, y_gain 97 */
		TV_OUT(TV_GAIN, 0x0081b697);
		TV_OUT(TV_CGMS, 0x000af317);
		TV_OUT(TV_TEST_MUX, 0x000001c3);
		TV_OUT(TV_TEST_MODE, 0x00000002);
		/*  PAL Timing */
		TV_OUT(TV_SYNC_1, 0x0020009e);
		TV_OUT(TV_SYNC_2, 0x011306b4);
		TV_OUT(TV_SYNC_3, 0x0006000c);
		TV_OUT(TV_SYNC_4, 0x0028020D);
		TV_OUT(TV_SYNC_5, 0x005e02fb);
		TV_OUT(TV_SYNC_6, 0x0006000c);
		TV_OUT(TV_SYNC_7, 0x00000012);
		TV_OUT(TV_BURST_V1, 0x0012020b);
		TV_OUT(TV_BURST_V2, 0x0016020c);
		TV_OUT(TV_BURST_V3, 0x00150209);
		TV_OUT(TV_BURST_V4, 0x0013020c);
		TV_OUT(TV_BURST_H, 0x00bf010b);
		TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
		TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);

		reg |= TVENC_CTL_TV_MODE_PAL_M;
		var->yres = 480;
		break;
	default:
		return -ENODEV;
	}

	reg |= TVENC_CTL_Y_FILTER_EN | TVENC_CTL_CR_FILTER_EN |
		TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN;

	/* DC offset to 0. */
	TV_OUT(TV_LEVEL, 0x00000000);
	TV_OUT(TV_OFFSET, 0x008080f0);

#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO
	reg |= TVENC_CTL_S_VIDEO_EN;
#endif
#if defined(CONFIG_FB_MSM_MDP31)
	TV_OUT(TV_DAC_INTF, 0x29);
#endif
	TV_OUT(TV_ENC_CTL, reg);

	if (!tvout_msm_state->hpd_initialized) {
		tvout_msm_state->hpd_initialized = TRUE;
		/* Load detect enable */
		reg = TV_IN(TV_DAC_INTF);
		reg |= TVENC_LOAD_DETECT_EN;
		TV_OUT(TV_DAC_INTF, reg);
	}

	tvout_msm_state->disp_powered_up = TRUE;
	tvout_msm_turn_on(TRUE);

	if (tvenc_pdata->poll) {
		/* Enable Load present & removal interrupts for Video1 */
		TV_OUT(TV_INTR_ENABLE, 0x5);

		/* Enable interrupts when display is on */
		enable_irq(tvout_msm_state->irq);
	}
	return 0;
}